xref: /llvm-project/llvm/test/Analysis/BasicAA/phi-aa.ll (revision 303c308e452c703c3d47940383ded3b2d3eefd56)
1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
3target triple = "x86_64-unknown-linux-gnu"
4
5; rdar://7282591
6
7@X = common global i32 0
8@Y = common global i32 0
9@Z = common global i32 0
10
11; CHECK-LABEL: foo
12; CHECK:  NoAlias: i32* %P, i32* @Z
13
14define void @foo(i32 %cond) nounwind {
15entry:
16  %"alloca point" = bitcast i32 0 to i32
17  %tmp = icmp ne i32 %cond, 0
18  br i1 %tmp, label %bb, label %bb1
19
20bb:
21  br label %bb2
22
23bb1:
24  br label %bb2
25
26bb2:
27  %P = phi ptr [ @X, %bb ], [ @Y, %bb1 ]
28  %tmp1 = load i32, ptr @Z, align 4
29  store i32 123, ptr %P, align 4
30  %tmp2 = load i32, ptr @Z, align 4
31  br label %return
32
33return:
34  ret void
35}
36
37; Pointers can vary in between iterations of loops.
38; PR18068
39
40; CHECK-LABEL: pr18068
41; CHECK: MayAlias: i32* %0, i32* %arrayidx5
42; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5
43
44define i32 @pr18068(ptr %jj7, ptr %j) {
45entry:
46  %oa5 = alloca [100 x i32], align 16
47  br label %codeRepl
48
49codeRepl:
50  %0 = phi ptr [ %arrayidx13, %for.body ], [ %j, %entry ]
51  %targetBlock = call i1 @cond(ptr %jj7)
52  br i1 %targetBlock, label %for.body, label %bye
53
54for.body:
55  %1 = load i32, ptr %jj7, align 4
56  %idxprom4 = zext i32 %1 to i64
57  %arrayidx5 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i64 %idxprom4
58  %2 = load i32, ptr %arrayidx5, align 4
59  %sub6 = sub i32 %2, 6
60  store i32 %sub6, ptr %arrayidx5, align 4
61  ; %0 and %arrayidx5 can alias! It is not safe to DSE the above store.
62  %3 = load i32, ptr %0, align 4
63  store i32 %3, ptr %arrayidx5, align 4
64  %sub11 = add i32 %1, -1
65  %idxprom12 = zext i32 %sub11 to i64
66  %arrayidx13 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i64 %idxprom12
67  load i32, ptr %arrayidx13
68  call void @inc(ptr %jj7)
69  br label %codeRepl
70
71bye:
72  %.reload = load i32, ptr %jj7, align 4
73  ret i32 %.reload
74}
75
76declare i1 @cond(ptr)
77
78declare void @inc(ptr)
79
80
81; When we have a chain of phis in nested loops we should recognise if there's
82; actually only one underlying value.
83; FIXME: All of these could be NoAlias.
84; CHECK-LABEL: loop_phi_chain
85; CHECK: MayAlias: i32* %val1, i32* @Y
86; CHECK: MayAlias: i32* %val2, i32* @Y
87; CHECK: MayAlias: i32* %val3, i32* @Y
88define void @loop_phi_chain(i32 %a, i32 %b, i32 %c) {
89entry:
90  br label %loop1
91
92loop1:
93  %n1 = phi i32 [ 0, %entry ], [ %add1, %loop2 ]
94  %val1 = phi ptr [ @X, %entry ], [ %val2, %loop2 ]
95  load i32, ptr %val1
96  %add1 = add i32 %n1, 1
97  %cmp1 = icmp ne i32 %n1, 32
98  br i1 %cmp1, label %loop2, label %end
99
100loop2:
101  %n2 = phi i32 [ 0, %loop1 ], [ %add2, %loop3 ]
102  %val2 = phi ptr [ %val1, %loop1 ], [ %val3, %loop3 ]
103  load i32, ptr %val2
104  %add2 = add i32 %n2, 1
105  %cmp2 = icmp ne i32 %n2, 32
106  br i1 %cmp2, label %loop3, label %loop1
107
108loop3:
109  %n3 = phi i32 [ 0, %loop2 ], [ %add3, %loop3 ]
110  %val3 = phi ptr [ %val2, %loop2 ], [ %val3, %loop3 ]
111  store i32 0, ptr %val3, align 4
112  store i32 0, ptr @Y, align 4
113  %add3 = add i32 %n3, 1
114  %cmp3 = icmp ne i32 %n3, 32
115  br i1 %cmp3, label %loop3, label %loop2
116
117end:
118  ret void
119}
120
121; CHECK-LABEL: phi_and_select
122; CHECK: MustAlias: i32* %p, i32* %s
123define void @phi_and_select(i1 %c, i1 %c2, ptr %x, ptr %y) {
124entry:
125  br i1 %c, label %true, label %false
126
127true:
128  br label %exit
129
130false:
131  br label %exit
132
133exit:
134  %p = phi ptr [ %x, %true ], [ %y, %false ]
135  %s = select i1 %c2, ptr %p, ptr %p
136  store i32 0, ptr %p
137  store i32 0, ptr %s
138  ret void
139}
140
141; CHECK-LABEL: phi_and_phi_cycle
142; CHECK: NoAlias: i32* %p1, i32* %p2
143define void @phi_and_phi_cycle(ptr noalias %x, ptr noalias %y) {
144entry:
145  br label %loop
146
147loop:
148  %p1 = phi ptr [ %x, %entry ], [ %p1.next, %loop ]
149  %p2 = phi ptr [ %y, %entry ], [ %p2.next, %loop ]
150  %p1.next = getelementptr i32, ptr %p1, i64 1
151  %p2.next = getelementptr i32, ptr %p1, i64 2
152  store i32 0, ptr %p1
153  store i32 0, ptr %p2
154  br label %loop
155}
156
157; CHECK-LABEL: phi_and_gep_unknown_size
158; CHECK: Just Mod:   call void @llvm.memset.p0.i32(ptr %g, i8 0, i32 %size, i1 false) <->   call void @llvm.memset.p0.i32(ptr %z, i8 0, i32 %size, i1 false)
159; TODO: This should be NoModRef.
160define void @phi_and_gep_unknown_size(i1 %c, ptr %x, ptr %y, ptr noalias %z, i32 %size) {
161entry:
162  br i1 %c, label %true, label %false
163
164true:
165  br label %exit
166
167false:
168  br label %exit
169
170exit:
171  %p = phi ptr [ %x, %true ], [ %y, %false ]
172  %g = getelementptr inbounds i8, ptr %p, i64 1
173  call void @llvm.memset.p0.i32(ptr %g, i8 0, i32 %size, i1 false)
174  call void @llvm.memset.p0.i32(ptr %z, i8 0, i32 %size, i1 false)
175  ret void
176}
177
178declare void @llvm.memset.p0.i32(ptr, i8, i32, i1)
179
180; CHECK-LABEL: unsound_inequality
181; CHECK: MayAlias:  i32* %arrayidx5, i32* %phi
182; CHECK: MayAlias:  i32* %arrayidx13, i32* %phi
183; CHECK: NoAlias:   i32* %arrayidx13, i32* %arrayidx5
184
185; When recursively reasoning about phis, we can't use predicates between
186; two values as we might be comparing the two from different iterations.
187define i32 @unsound_inequality(ptr %jj7, ptr %j) {
188entry:
189  %oa5 = alloca [100 x i32], align 16
190  br label %for.body
191
192for.body:                                         ; preds = %for.body, %entry
193  %phi = phi ptr [ %arrayidx13, %for.body ], [ %j, %entry ]
194  load i32, ptr %phi
195  %idx = load i32, ptr %jj7, align 4
196  %arrayidx5 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i32 %idx
197  store i32 0, ptr %arrayidx5, align 4
198  store i32 0, ptr %phi, align 4
199  %notequal = add i32 %idx, 1
200  %arrayidx13 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i32 %notequal
201  store i32 0, ptr %arrayidx13, align 4
202  br label %for.body
203}
204
205; CHECK-LABEL: single_arg_phi
206; CHECK: NoAlias: i32* %ptr, i32* %ptr.next
207; CHECK: MustAlias: i32* %ptr, i32* %ptr.phi
208; CHECK: MustAlias: i32* %ptr.next, i32* %ptr.next.phi
209define void @single_arg_phi(ptr %ptr.base) {
210entry:
211  br label %loop
212
213loop:
214  %ptr = phi ptr [ %ptr.base, %entry ], [ %ptr.next, %split ]
215  %ptr.next = getelementptr inbounds i32, ptr %ptr, i64 1
216  load i32, ptr %ptr
217  load i32, ptr %ptr.next
218  br label %split
219
220split:
221  %ptr.phi = phi ptr [ %ptr, %loop ]
222  %ptr.next.phi = phi ptr [ %ptr.next, %loop ]
223  load i32, ptr %ptr.phi
224  load i32, ptr %ptr.next.phi
225  br label %loop
226}
227
228; CHECK-LABEL: phi_of_geps_based_on_alloca
229; CHECK: NoAlias:	i32* %gep3, i32* %phi
230define void @phi_of_geps_based_on_alloca(i1 %c) {
231  %a = alloca [3 x i32]
232  br i1 %c, label %if, label %else
233
234if:
235  %gep1 = getelementptr i32, ptr %a, i64 1
236  br label %join
237
238else:
239  %gep2 = getelementptr i32, ptr %a, i64 2
240  br label %join
241
242join:
243  %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ]
244  %gep3 = getelementptr i32, ptr %a, i64 3
245  load i32, ptr %phi
246  load i32, ptr %gep3
247  ret void
248}
249
250; Don't crash with an unreachable predecessor.
251; CHECK-LABEL: pr59360
252; CHECK: MayAlias: i32* %loaded.ptr, i32* %phi
253define void @pr59360() {
254entry:
255  br label %outer
256
257loopexit:                                         ; No predecessors!
258  br label %outer
259
260outer:                                            ; preds = %loopexit, %entry
261  %phi = phi ptr [ %loaded.ptr, %loopexit ], [ null, %entry ]
262  store i32 0, ptr %phi, align 4
263  %loaded.ptr = load ptr, ptr null, align 8
264  %0 = load i32, ptr %loaded.ptr, align 4
265  ret void
266}
267