1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s
2
3; CHECK: Function: t1
4; CHECK: NoAlias: i32* %gep1, i32* %gep2
5define void @t1([8 x i32]* %p, i32 %addend, i32* %q) {
6  %knownnonzero = load i32, i32* %q, !range !0
7  %add = add nsw nuw i32 %addend, %knownnonzero
8  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend
9  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add
10  load i32, i32* %gep1
11  load i32, i32* %gep2
12  ret void
13}
14
15; CHECK: Function: t2
16; CHECK: MayAlias: i32* %gep1, i32* %gep2
17define void @t2([8 x i32]* %p, i32 %addend, i32* %q) {
18  %knownnonzero = load i32, i32* %q, !range !0
19  %add = add nsw nuw i32 %addend, %knownnonzero
20  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
21  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
22  load i32, i32* %gep1
23  load i32, i32* %gep2
24  ret void
25}
26
27; CHECK: Function: t3
28; CHECK: MustAlias: i32* %gep1, i32* %gep2
29define void @t3([8 x i32]* %p, i32 %addend, i32* %q) {
30  %knownnonzero = load i32, i32* %q, !range !0
31  %add = add nsw nuw i32 %addend, %knownnonzero
32  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
33  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 0, i32 %add
34  load i32, i32* %gep1
35  load i32, i32* %gep2
36  ret void
37}
38
39; CHECK: Function: t4
40; CHECK: MayAlias: i32* %gep1, i32* %gep2
41define void @t4([8 x i32]* %p, i32 %addend, i32* %q) {
42  %knownnonzero = load i32, i32* %q, !range !0
43  %add = add nsw nuw i32 %addend, %knownnonzero
44  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 1, i32 %addend
45  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 %add, i32 %add
46  load i32, i32* %gep1
47  load i32, i32* %gep2
48  ret void
49}
50
51; CHECK: Function: t5
52; CHECK: MayAlias: i64* %bc, i32* %gep2
53define void @t5([8 x i32]* %p, i32 %addend, i32* %q) {
54  %knownnonzero = load i32, i32* %q, !range !0
55  %add = add nsw nuw i32 %addend, %knownnonzero
56  %gep1 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %addend
57  %gep2 = getelementptr [8 x i32], [8 x i32]* %p, i32 2, i32 %add
58  %bc = bitcast i32* %gep1 to i64*
59  load i32, i32* %gep2
60  load i64, i64* %bc
61  ret void
62}
63
64; CHECK-LABEL: Function: add_non_zero_simple
65; CHECK: NoAlias: i32* %gep1, i32* %gep2
66define void @add_non_zero_simple(i32* %p, i32 %addend, i32* %q) {
67  %knownnonzero = load i32, i32* %q, !range !0
68  %add = add i32 %addend, %knownnonzero
69  %gep1 = getelementptr i32, i32* %p, i32 %addend
70  %gep2 = getelementptr i32, i32* %p, i32 %add
71  load i32, i32* %gep1
72  load i32, i32* %gep2
73  ret void
74}
75
76; CHECK-LABEL: Function: add_non_zero_different_scales
77; CHECK: MayAlias: i32* %gep1, i16* %gep2
78define void @add_non_zero_different_scales(i32* %p, i32 %addend, i32* %q) {
79  %knownnonzero = load i32, i32* %q, !range !0
80  %add = add i32 %addend, %knownnonzero
81  %p16 = bitcast i32* %p to i16*
82  %gep1 = getelementptr i32, i32* %p, i32 %addend
83  %gep2 = getelementptr i16, i16* %p16, i32 %add
84  load i32, i32* %gep1
85  load i16, i16* %gep2
86  ret void
87}
88
89; CHECK-LABEL: Function: add_non_zero_different_sizes
90; CHECK: NoAlias: i16* %gep1.16, i32* %gep2
91; CHECK: NoAlias: i32* %gep1, i16* %gep2.16
92; CHECK: NoAlias: i16* %gep1.16, i16* %gep2.16
93; CHECK: MayAlias: i64* %gep1.64, i32* %gep2
94; CHECK: MayAlias: i64* %gep1.64, i16* %gep2.16
95; CHECK: MayAlias: i32* %gep1, i64* %gep2.64
96; CHECK: MayAlias: i16* %gep1.16, i64* %gep2.64
97; CHECK: MayAlias: i64* %gep1.64, i64* %gep2.64
98define void @add_non_zero_different_sizes(i32* %p, i32 %addend, i32* %q) {
99  %knownnonzero = load i32, i32* %q, !range !0
100  %add = add i32 %addend, %knownnonzero
101  %gep1 = getelementptr i32, i32* %p, i32 %addend
102  %gep2 = getelementptr i32, i32* %p, i32 %add
103  %gep1.16 = bitcast i32* %gep1 to i16*
104  %gep2.16 = bitcast i32* %gep2 to i16*
105  %gep1.64 = bitcast i32* %gep1 to i64*
106  %gep2.64 = bitcast i32* %gep2 to i64*
107  load i32, i32* %gep1
108  load i32, i32* %gep2
109  load i16, i16* %gep1.16
110  load i16, i16* %gep2.16
111  load i64, i64* %gep1.64
112  load i64, i64* %gep2.64
113  ret void
114}
115
116
117; CHECK-LABEL: add_non_zero_with_offset
118; MayAlias: i32* %gep1, i32* %gep2
119; NoAlias: i16* %gep1.16, i16* %gep2.16
120define void @add_non_zero_with_offset(i32* %p, i32 %addend, i32* %q) {
121  %knownnonzero = load i32, i32* %q, !range !0
122  %add = add i32 %addend, %knownnonzero
123  %p.8 = bitcast i32* %p to i8*
124  %p.off.8 = getelementptr i8, i8* %p.8, i32 2
125  %p.off = bitcast i8* %p.off.8 to i32*
126  %gep1 = getelementptr i32, i32* %p.off, i32 %addend
127  %gep2 = getelementptr i32, i32* %p, i32 %add
128  %gep1.16 = bitcast i32* %gep1 to i16*
129  %gep2.16 = bitcast i32* %gep2 to i16*
130  load i32, i32* %gep1
131  load i32, i32* %gep2
132  load i16, i16* %gep1.16
133  load i16, i16* %gep2.16
134  ret void
135}
136
137; CHECK-LABEL: Function: add_non_zero_assume
138; CHECK: NoAlias: i32* %gep1, i32* %gep2
139define void @add_non_zero_assume(i32* %p, i32 %addend, i32 %knownnonzero) {
140  %cmp = icmp ne i32 %knownnonzero, 0
141  call void @llvm.assume(i1 %cmp)
142  %add = add i32 %addend, %knownnonzero
143  %gep1 = getelementptr i32, i32* %p, i32 %addend
144  %gep2 = getelementptr i32, i32* %p, i32 %add
145  load i32, i32* %gep1
146  load i32, i32* %gep2
147  ret void
148}
149
150; CHECK-LABEL: non_zero_index_simple
151; CHECK: NoAlias: i32* %gep, i32* %p
152; CHECK: NoAlias: i16* %gep.16, i32* %p
153; CHECK: MayAlias: i64* %gep.64, i32* %p
154define void @non_zero_index_simple(i32* %p, i32* %q) {
155  %knownnonzero = load i32, i32* %q, !range !0
156  %gep = getelementptr i32, i32* %p, i32 %knownnonzero
157  %gep.16 = bitcast i32* %gep to i16*
158  %gep.64 = bitcast i32* %gep to i64*
159  load i32, i32* %p
160  load i32, i32* %gep
161  load i16, i16* %gep.16
162  load i64, i64* %gep.64
163  ret void
164}
165
166; CHECK-LABEL: non_zero_index_with_offset
167; CHECK: MayAlias: i32* %gep, i32* %p
168; CHECK: NoAlias: i16* %gep.16, i32* %p
169define void @non_zero_index_with_offset(i32* %p, i32* %q) {
170  %knownnonzero = load i32, i32* %q, !range !0
171  %p.8 = bitcast i32* %p to i8*
172  %p.off.8 = getelementptr i8, i8* %p.8, i32 2
173  %p.off = bitcast i8* %p.off.8 to i32*
174  %gep = getelementptr i32, i32* %p.off, i32 %knownnonzero
175  %gep.16 = bitcast i32* %gep to i16*
176  load i32, i32* %p
177  load i32, i32* %gep
178  load i16, i16* %gep.16
179  ret void
180}
181
182; CHECK-LABEL: non_zero_index_assume
183; CHECK: NoAlias: i32* %gep, i32* %p
184define void @non_zero_index_assume(i32* %p, i32 %knownnonzero) {
185  %cmp = icmp ne i32 %knownnonzero, 0
186  call void @llvm.assume(i1 %cmp)
187  %gep = getelementptr i32, i32* %p, i32 %knownnonzero
188  load i32, i32* %p
189  load i32, i32* %gep
190  ret void
191}
192
193declare void @llvm.assume(i1)
194
195!0 = !{ i32 1, i32 0 }
196