1target datalayout =
2"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"
3
4; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
5
6; ptr_phi and ptr2_phi do not alias.
7; CHECK: test_noalias_1
8; CHECK: NoAlias: i32* %ptr2_phi, i32* %ptr_phi
9; CHECK: NoAlias: i32* %ptr2_inc, i32* %ptr_inc
10define i32 @test_noalias_1(i32* %ptr2, i32 %count, i32* %coeff) {
11entry:
12  %ptr = getelementptr inbounds i32, i32* %ptr2, i64 1
13  br label %while.body
14
15while.body:
16  %num = phi i32 [ %count, %entry ], [ %dec, %while.body ]
17  %ptr_phi = phi i32* [ %ptr, %entry ], [ %ptr_inc, %while.body ]
18  %ptr2_phi = phi i32* [ %ptr2, %entry ], [ %ptr2_inc, %while.body ]
19  %result.09 = phi i32 [ 0 , %entry ], [ %add, %while.body ]
20  %dec = add nsw i32 %num, -1
21  %0 = load i32, i32* %ptr_phi, align 4
22  store i32 %0, i32* %ptr2_phi, align 4
23  %1 = load i32, i32* %coeff, align 4
24  %2 = load i32, i32* %ptr_phi, align 4
25  %mul = mul nsw i32 %1, %2
26  %add = add nsw i32 %mul, %result.09
27  %tobool = icmp eq i32 %dec, 0
28  %ptr_inc = getelementptr inbounds i32, i32* %ptr_phi, i64 1
29  %ptr2_inc = getelementptr inbounds i32, i32* %ptr2_phi, i64 1
30  load i32, i32* %ptr_inc
31  load i32, i32* %ptr2_inc
32  br i1 %tobool, label %the_exit, label %while.body
33
34the_exit:
35  ret i32 %add
36}
37
38; CHECK: test_noalias_2
39; CHECK-DAG: NoAlias: i32* %ptr_outer_phi, i32* %ptr_outer_phi2
40; CHECK-DAG: NoAlias: i32* %ptr2_inc_outer, i32* %ptr_inc_outer
41; CHECK-DAG: NoAlias: i32* %ptr2_phi, i32* %ptr_phi
42; CHECK-DAG: NoAlias: i32* %ptr2_inc, i32* %ptr_inc
43define i32 @test_noalias_2(i32* %ptr2, i32 %count, i32* %coeff) {
44entry:
45  %ptr = getelementptr inbounds i32, i32* %ptr2, i64 1
46  br label %outer.while.header
47
48outer.while.header:
49  %ptr_outer_phi = phi i32* [%ptr_inc_outer, %outer.while.backedge], [ %ptr, %entry]
50  %ptr_outer_phi2 = phi i32* [%ptr2_inc_outer, %outer.while.backedge], [ %ptr2, %entry]
51  %num.outer = phi i32 [ %count, %entry ], [ %dec.outer, %outer.while.backedge ]
52  %ignore1 = load i32, i32* %ptr_outer_phi
53  %ignore2 = load i32, i32* %ptr_outer_phi2
54  br label %while.body
55
56while.body:
57  %num = phi i32 [ %count, %outer.while.header ], [ %dec, %while.body ]
58  %ptr_phi = phi i32* [ %ptr_outer_phi, %outer.while.header ], [ %ptr_inc, %while.body ]
59  %ptr2_phi = phi i32* [ %ptr_outer_phi2, %outer.while.header ], [ %ptr2_inc, %while.body ]
60  %result.09 = phi i32 [ 0 , %outer.while.header ], [ %add, %while.body ]
61  %dec = add nsw i32 %num, -1
62  %0 = load i32, i32* %ptr_phi, align 4
63  store i32 %0, i32* %ptr2_phi, align 4
64  %1 = load i32, i32* %coeff, align 4
65  %2 = load i32, i32* %ptr_phi, align 4
66  %mul = mul nsw i32 %1, %2
67  %add = add nsw i32 %mul, %result.09
68  %tobool = icmp eq i32 %dec, 0
69  %ptr_inc = getelementptr inbounds i32, i32* %ptr_phi, i64 1
70  %ptr2_inc = getelementptr inbounds i32, i32* %ptr2_phi, i64 1
71  load i32, i32* %ptr_inc
72  load i32, i32* %ptr2_inc
73  br i1 %tobool, label %outer.while.backedge, label %while.body
74
75outer.while.backedge:
76  %ptr_inc_outer = getelementptr inbounds i32, i32* %ptr_phi, i64 1
77  %ptr2_inc_outer = getelementptr inbounds i32, i32* %ptr2_phi, i64 1
78  load i32, i32* %ptr_inc_outer
79  load i32, i32* %ptr2_inc_outer
80  %dec.outer = add nsw i32 %num.outer, -1
81  %br.cond = icmp eq i32 %dec.outer, 0
82  br i1 %br.cond, label %the_exit, label %outer.while.header
83
84the_exit:
85  ret i32 %add
86}
87
88; CHECK: test_noalias_3
89; CHECK: MayAlias: i8* %ptr2_phi, i8* %ptr_phi
90define i32 @test_noalias_3(i8* noalias %x, i8* noalias %y, i8* noalias %z,
91                           i32 %count) {
92entry:
93  br label %while.body
94
95while.body:
96  %num = phi i32 [ %count, %entry ], [ %dec, %while.body ]
97  %ptr_phi = phi i8* [ %x, %entry ], [ %z, %while.body ]
98  %ptr2_phi = phi i8* [ %y, %entry ], [ %ptr_phi, %while.body ]
99  load i8, i8* %ptr_phi
100  load i8, i8* %ptr2_phi
101  %dec = add nsw i32 %num, -1
102  %tobool = icmp eq i32 %dec, 0
103  br i1 %tobool, label %the_exit, label %while.body
104
105the_exit:
106  ret i32 1
107}
108
109; CHECK-LABEL: test_different_stride_noalias
110; CHECK: NoAlias: i8* %x.base, i16* %y.base
111; CHECK: NoAlias: i8* %x, i16* %y
112; CHECK: NoAlias: i8* %x.next, i16* %y.next
113define void @test_different_stride_noalias(i1 %c, i8* noalias %x.base, i16* noalias %y.base) {
114entry:
115  load i8, i8* %x.base
116  load i16, i16* %y.base
117  br label %loop
118
119loop:
120  %x = phi i8* [ %x.base, %entry ], [ %x.next, %loop ]
121  %y = phi i16* [ %y.base, %entry ], [ %y.next, %loop ]
122  load i8, i8* %x
123  load i16, i16* %y
124  %x.next = getelementptr i8, i8* %x, i64 1
125  %y.next = getelementptr i16, i16* %y, i64 1
126  load i8, i8* %x.next
127  load i16, i16* %y.next
128  br i1 %c, label %loop, label %exit
129
130exit:
131  ret void
132}
133
134; CHECK-LABEL: test_no_loop_mustalias
135; CHECK: MustAlias: i16* %z16, i8* %z8
136define void @test_no_loop_mustalias(i1 %c, i8* noalias %x8, i8* noalias %y8) {
137  br i1 %c, label %if, label %else
138
139if:
140  %x16 = bitcast i8* %x8 to i16*
141  br label %end
142
143else:
144  %y16 = bitcast i8* %y8 to i16*
145  br label %end
146
147end:
148  %z8 = phi i8* [ %x8, %if ], [ %y8, %else ]
149  %z16 = phi i16* [ %x16, %if ], [ %y16, %else ]
150  load i8, i8* %z8
151  load i16, i16* %z16
152  ret void
153}
154
155; CHECK-LABEL: test_same_stride_mustalias
156; CHECK: MustAlias: i8* %x.base, i4* %y.base
157; CHECK: MayAlias: i8* %x, i4* %y
158; CHECK: MayAlias: i8* %x.next, i4* %y.next
159; TODO: (x, y) could be MustAlias
160define void @test_same_stride_mustalias(i1 %c, i8* noalias %x.base) {
161entry:
162  %y.base = bitcast i8* %x.base to i4*
163  load i8, i8* %x.base
164  load i4, i4* %y.base
165  br label %loop
166
167loop:
168  %x = phi i8* [ %x.base, %entry ], [ %x.next, %loop ]
169  %y = phi i4* [ %y.base, %entry ], [ %y.next, %loop ]
170  load i8, i8* %x
171  load i4, i4* %y
172  %x.next = getelementptr i8, i8* %x, i64 1
173  %y.next = getelementptr i4, i4* %y, i64 1
174  load i8, i8* %x.next
175  load i4, i4* %y.next
176  br i1 %c, label %loop, label %exit
177
178exit:
179  ret void
180}
181
182; CHECK-LABEL: test_different_stride_mustalias
183; CHECK: MustAlias: i8* %x.base, i16* %y.base
184; CHECK: MayAlias: i8* %x, i16* %y
185; CHECK: MayAlias: i8* %x.next, i16* %y.next
186; Even though the base pointers MustAlias, the different strides don't preserve
187; this property across iterations.
188define void @test_different_stride_mustalias(i1 %c, i8* noalias %x.base) {
189entry:
190  %y.base = bitcast i8* %x.base to i16*
191  load i8, i8* %x.base
192  load i16, i16* %y.base
193  br label %loop
194
195loop:
196  %x = phi i8* [ %x.base, %entry ], [ %x.next, %loop ]
197  %y = phi i16* [ %y.base, %entry ], [ %y.next, %loop ]
198  load i8, i8* %x
199  load i16, i16* %y
200  %x.next = getelementptr i8, i8* %x, i64 1
201  %y.next = getelementptr i16, i16* %y, i64 1
202  load i8, i8* %x.next
203  load i16, i16* %y.next
204  br i1 %c, label %loop, label %exit
205
206exit:
207  ret void
208}
209