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: test_no_lower_bound
5 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
6 define void @test_no_lower_bound(ptr %p, i64 %i) {
7 %a = getelementptr i8, ptr %p, i64 4
8 %b = getelementptr nuw i8, ptr %p, i64 %i
16 ; CHECK-LABEL: test_lower_bound_lt_size
18 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
19 define void @test_lower_bound_lt_size(ptr %p, i64 %i) {
20 %a = getelementptr i8, ptr %p
21 %add = getelementptr nuw i8, ptr %p, i64 2
22 %b = getelementptr nuw i8, ptr %add, i64 %i
30 ; CHECK-LABEL: test_lower_bound_ge_size
32 ; CHECK-DAG: NoAlias: i32* %a, i32* %b
33 define void @test_lower_bound_ge_size(ptr %p, i64 %i) {
34 %a = getelementptr i8, ptr %p
35 %add = getelementptr nuw i8, ptr %p, i64 4
36 %b = getelementptr nuw i8, ptr %add, i64 %i
44 ; CHECK-LABEL: test_not_all_nuw
46 ; If part of the addressing is done with non-nuw GEPs, we can't use properties
47 ; implied by the last GEP with the whole offset. In this case, the calculation
48 ; of %add (%p + 4) could wrap the pointer index type, such that %add +<nuw> %i
49 ; could still alias with %p.
51 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
52 define void @test_not_all_nuw(ptr %p, i64 %i) {
53 %a = getelementptr i8, ptr %p
54 %add = getelementptr i8, ptr %p, i64 4
55 %b = getelementptr nuw i8, ptr %add, i64 %i
63 ; CHECK-LABEL: test_multi_step_not_all_nuw
65 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
66 define void @test_multi_step_not_all_nuw(ptr %p, i64 %i, i64 %j, i64 %k) {
67 %a = getelementptr i8, ptr %p
68 %add = getelementptr i8, ptr %p, i64 4
69 %step1 = getelementptr i8, ptr %add, i64 %i
70 %step2 = getelementptr i8, ptr %step1, i64 %j
71 %b = getelementptr nuw i8, ptr %step2, i64 %k
79 ; CHECK-LABEL: test_multi_step_all_nuw
81 ; CHECK-DAG: NoAlias: i32* %a, i32* %b
82 define void @test_multi_step_all_nuw(ptr %p, i64 %i, i64 %j, i64 %k) {
83 %a = getelementptr i8, ptr %p
84 %add = getelementptr nuw i8, ptr %p, i64 4
85 %step1 = getelementptr nuw i8, ptr %add, i64 %i
86 %step2 = getelementptr nuw i8, ptr %step1, i64 %j
87 %b = getelementptr nuw i8, ptr %step2, i64 %k
95 %struct = type { i64, [2 x i32], i64 }
97 ; CHECK-LABEL: test_struct_no_nuw
99 ; The array access may alias with the struct elements before and after, because
100 ; we cannot prove that (%arr + %i) does not alias with the base pointer %p.
102 ; CHECK-DAG: MayAlias: i32* %arrayidx, i64* %st
103 ; CHECK-DAG: NoAlias: i64* %after, i64* %st
104 ; CHECK-DAG: MayAlias: i64* %after, i32* %arrayidx
106 define void @test_struct_no_nuw(ptr %st, i64 %i) {
107 %arr = getelementptr i8, ptr %st, i64 8
108 %arrayidx = getelementptr [2 x i32], ptr %arr, i64 0, i64 %i
109 %after = getelementptr i8, ptr %st, i64 16
112 load i32, ptr %arrayidx
118 ; CHECK-LABEL: test_struct_nuw
120 ; We can prove that the array access does not alias with struct element before,
121 ; because we can prove that (%arr +<nuw> %i) does not wrap the pointer index
122 ; type (add nuw). The array access may still alias with the struct element
123 ; after, as the add nuw property does not preclude this.
125 ; CHECK-DAG: NoAlias: i32* %arrayidx, i64* %st
126 ; CHECK-DAG: NoAlias: i64* %after, i64* %st
127 ; CHECK-DAG: MayAlias: i64* %after, i32* %arrayidx
129 define void @test_struct_nuw(ptr %st, i64 %i) {
130 %arr = getelementptr nuw i8, ptr %st, i64 8
131 %arrayidx = getelementptr nuw [2 x i32], ptr %arr, i64 0, i64 %i
132 %after = getelementptr nuw i8, ptr %st, i64 16
135 load i32, ptr %arrayidx
141 ; CHECK-LABEL: constant_offset_overflow
143 ; If subtraction of constant offsets could overflow in an unsigned sense, we
144 ; cannot prove the lower bound between the GEPs and so they may still alias.
146 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
148 define void @constant_offset_overflow(ptr %p, i64 %i) {
149 %a = getelementptr i8, ptr %p, i64 -8
150 %add = getelementptr nuw i8, ptr %p, i64 4
151 %b = getelementptr nuw i8, ptr %add, i64 %i
159 ; CHECK-LABEL: equal_var_idx_noalias
161 ; If GEPs have equal variable indices, we can prove NoAlias when the Scale of
162 ; the RHS GEP is greater, as in this scenario the constant lower bound holds.
164 ; CHECK-DAG: NoAlias: i32* %a, i32* %b
166 define void @equal_var_idx_noalias(ptr %p, i64 %i) {
167 %a = getelementptr i8, ptr %p, i64 %i
169 %add = getelementptr nuw i8, ptr %p, i64 4
170 %b = getelementptr nuw i16, ptr %add, i64 %i
178 ; CHECK-LABEL: equal_var_idx_alias
180 ; If GEPs have equal variable indices, we cannot prove NoAlias when the Scale of
181 ; the RHS GEP is ult Scale of the LHS GEP.
183 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
185 define void @equal_var_idx_alias(ptr %p, i64 %i) {
186 %a = getelementptr i32, ptr %p, i64 %i
188 %add = getelementptr nuw i8, ptr %p, i64 4
189 %b = getelementptr nuw i16, ptr %add, i64 %i
197 ; CHECK-LABEL: both_var_idx
199 ; If the RHS GEP has unmatched variable indices, we cannot prove a constant
200 ; lower bound between GEPs.
202 ; CHECK-DAG: MayAlias: i32* %a, i32* %b
204 define void @both_var_idx(ptr %p, i64 %i, i64 %j) {
205 %a = getelementptr i8, ptr %p, i64 %i
207 %add = getelementptr nuw i8, ptr %p, i64 4
208 %b = getelementptr nuw i8, ptr %add, i64 %j
216 ; CHECK-LABEL: add_no_nuw
217 ; CHECK: MayAlias: i8* %gep, i8* %p
218 define i8 @add_no_nuw(ptr %p, i64 %n) {
222 %gep = getelementptr nuw i8, ptr %p, i64 %add
223 %val = load i8, ptr %gep
227 ; CHECK-LABEL: add_nuw
228 ; CHECK: NoAlias: i8* %gep, i8* %p
229 define i8 @add_nuw(ptr %p, i64 %n) {
232 %add = add nuw i64 %n, 1
233 %gep = getelementptr nuw i8, ptr %p, i64 %add
234 %val = load i8, ptr %gep
238 ; CHECK-LABEL: add_no_nuw
239 ; CHECK: MayAlias: i8* %gep, i16* %p
240 define i8 @add_no_nuw_scale(ptr %p, i64 %n) {
244 %gep = getelementptr nuw i16, ptr %p, i64 %add
245 %val = load i8, ptr %gep
249 ; CHECK-LABEL: add_nuw
250 ; CHECK: NoAlias: i8* %gep, i16* %p
251 define i8 @add_nuw_scale(ptr %p, i64 %n) {
254 %add = add nuw i64 %n, 1
255 %gep = getelementptr nuw i16, ptr %p, i64 %add
256 %val = load i8, ptr %gep
260 ; CHECK-LABEL: sub_nuw
261 ; CHECK: MayAlias: i8* %gep, i8* %p
262 define i8 @sub_nuw(ptr %p, i64 %n) {
265 %add = sub nuw i64 %n, 1
266 %gep = getelementptr nuw i8, ptr %p, i64 %add
267 %val = load i8, ptr %gep
271 ; CHECK-LABEL: mul_no_nuw
272 ; CHECK: MayAlias: i8* %gep, i16* %p
273 define i8 @mul_no_nuw(ptr %p, i64 %n) {
276 %add = add nuw i64 %n, 1
277 %mul = mul i64 %add, 2
278 %gep = getelementptr nuw i8, ptr %p, i64 %mul
279 %val = load i8, ptr %gep
283 ; CHECK-LABEL: mul_nuw
284 ; CHECK: NoAlias: i8* %gep, i16* %p
285 define i8 @mul_nuw(ptr %p, i64 %n) {
288 %add = add nuw i64 %n, 1
289 %mul = mul nuw i64 %add, 2
290 %gep = getelementptr nuw i8, ptr %p, i64 %mul
291 %val = load i8, ptr %gep
295 ; CHECK-LABEL: shl_no_nuw
296 ; CHECK: MayAlias: i8* %gep, i16* %p
297 define i8 @shl_no_nuw(ptr %p, i64 %n) {
300 %add = add nuw i64 %n, 1
301 %shl = shl i64 %add, 1
302 %gep = getelementptr nuw i8, ptr %p, i64 %shl
303 %val = load i8, ptr %gep
307 ; CHECK-LABEL: shl_nuw
308 ; CHECK: NoAlias: i8* %gep, i16* %p
309 define i8 @shl_nuw(ptr %p, i64 %n) {
312 %add = add nuw i64 %n, 1
313 %shl = shl nuw i64 %add, 1
314 %gep = getelementptr nuw i8, ptr %p, i64 %shl
315 %val = load i8, ptr %gep