xref: /llvm-project/llvm/test/Analysis/BasicAA/assume-index-positive.ll (revision 1aee1e1f4c4b504becc06521546de992a662694b)
1; RUN: opt -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info %s 2>&1 | FileCheck %s
2
3; %col.ptr.1 and %col.ptr.2 do not alias, if we know that %skip >= 0, because
4; the distance between %col.ptr.1 and %col.ptr.2 is %skip + 6 and we load 6
5; elements.
6define void @test1(ptr %ptr, i32 %skip) {
7; CHECK-LABEL: Function: test1: 2 pointers, 1 call sites
8; CHECK-NEXT:  NoAlias: <6 x double>* %col.ptr.2, <6 x double>* %ptr
9;
10  %gt = icmp sgt i32 %skip, -1
11  call void @llvm.assume(i1 %gt)
12  %stride = add nsw nuw i32 %skip, 6
13  %lv.1 = load <6 x double>, ptr %ptr, align 8
14  %col.ptr.2 = getelementptr double, ptr %ptr, i32 %stride
15  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
16  %res.1 = fadd <6 x double> %lv.1, %lv.1
17  %res.2 = fadd <6 x double> %lv.2, %lv.2
18  store <6 x double> %res.1, ptr %ptr, align 8
19  store <6 x double> %res.2, ptr %col.ptr.2, align 8
20  ret void
21}
22
23; Same as @test1, but now we do not have an assume guaranteeing %skip >= 0.
24define void @test2(ptr %ptr, i32 %skip) {
25; CHECK-LABEL: Function: test2: 2 pointers, 0 call sites
26; CHECK-NEXT:    MayAlias:  <6 x double>* %col.ptr.2, <6 x double>* %ptr
27;
28  %stride = add nsw nuw i32 %skip, 6
29  %lv.1 = load <6 x double>, ptr %ptr, align 8
30  %col.ptr.2 = getelementptr double, ptr  %ptr, i32 %stride
31  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
32  %res.1 = fadd <6 x double> %lv.1, %lv.1
33  %res.2 = fadd <6 x double> %lv.2, %lv.2
34  store <6 x double> %res.1, ptr %ptr, align 8
35  store <6 x double> %res.2, ptr %col.ptr.2, align 8
36  ret void
37}
38
39; Same as @test1, this time the assume just guarantees %skip > -3, which is
40; enough to derive NoAlias for %ptr and %col.ptr.2 (distance is more than 3
41; doubles, and we load 1 double), but not %col.ptr.1 and %col.ptr.2 (distance
42; is more than 3 doubles, and we load 6 doubles).
43define void @test3(ptr %ptr, i32 %skip) {
44; CHECK-LABEL: Function: test3: 2 pointers, 1 call sites
45; CHECK-NEXT:   MayAlias:	<6 x double>* %col.ptr.2, <6 x double>* %ptr
46;
47  %gt = icmp sgt i32 %skip, -3
48  call void @llvm.assume(i1 %gt)
49  %stride = add nsw nuw i32 %skip, 6
50  %lv.1 = load <6 x double>, ptr %ptr, align 8
51  %col.ptr.2 = getelementptr double, ptr %ptr, i32 %stride
52  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
53  %res.1 = fadd <6 x double> %lv.1, %lv.1
54  %res.2 = fadd <6 x double> %lv.2, %lv.2
55  store <6 x double> %res.1, ptr %ptr, align 8
56  store <6 x double> %res.2, ptr %col.ptr.2, align 8
57  ret void
58}
59
60; Same as @test1, but the assume uses the sge predicate for %skip >= 0.
61define void @test4(ptr %ptr, i32 %skip) {
62; CHECK-LABEL: Function: test4: 2 pointers, 1 call sites
63; CHECK-NEXT:    NoAlias:	<6 x double>* %col.ptr.2, <6 x double>* %ptr
64;
65  %gt = icmp sge i32 %skip, 0
66  call void @llvm.assume(i1 %gt)
67  %stride = add nsw nuw i32 %skip, 6
68  %lv.1 = load <6 x double>, ptr %ptr, align 8
69  %col.ptr.2 = getelementptr double, ptr %ptr, i32 %stride
70  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
71  %res.1 = fadd <6 x double> %lv.1, %lv.1
72  %res.2 = fadd <6 x double> %lv.2, %lv.2
73  store <6 x double> %res.1, ptr %ptr, align 8
74  store <6 x double> %res.2, ptr %col.ptr.2, align 8
75  ret void
76}
77
78define void @symmetry(ptr %ptr, i32 %a, i32 %b, i32 %c) {
79; CHECK-LABEL: Function: symmetry
80; CHECK: NoAlias: i8* %gep1, i8* %gep2
81;
82  %b.cmp = icmp slt i32 %b, 0
83  call void @llvm.assume(i1 %b.cmp)
84  %gep1 = getelementptr [0 x i8], ptr %ptr, i32 %a, i32 %b
85  load i8, ptr %gep1
86  call void @barrier()
87  %c.cmp = icmp sgt i32 %c, -1
88  call void @llvm.assume(i1 %c.cmp)
89  %c.off = add nuw nsw i32 %c, 1
90  %gep2 = getelementptr [0 x i8], ptr %ptr, i32 %a, i32 %c.off
91  load i8, ptr %gep2
92  ret void
93}
94
95; %ptr.neg and %ptr.shl may alias, as the shl renders the previously
96; non-negative value potentially negative.
97define void @shl_of_non_negative(ptr %ptr, i64 %a) {
98; CHECK-LABEL: Function: shl_of_non_negative
99; CHECK: NoAlias: i8* %ptr.a, i8* %ptr.neg
100; CHECK: MayAlias: i8* %ptr.neg, i8* %ptr.shl
101;
102  %a.cmp = icmp sge i64 %a, 0
103  call void @llvm.assume(i1 %a.cmp)
104  %ptr.neg = getelementptr i8, ptr %ptr, i64 -2
105  %ptr.a = getelementptr i8, ptr %ptr, i64 %a
106  %shl = shl i64 %a, 1
107  %ptr.shl = getelementptr i8, ptr %ptr, i64 %shl
108  load i8, ptr %ptr.a
109  load i8, ptr %ptr.neg
110  load i8, ptr %ptr.shl
111  ret void
112}
113
114; Unlike the previous case, %ptr.neg and %ptr.shl can't alias, because
115; shl nsw of non-negative is non-negative.
116define void @shl_nsw_of_non_negative(ptr %ptr, i64 %a) {
117; CHECK-LABEL: Function: shl_nsw_of_non_negative
118; CHECK: NoAlias: i8* %ptr.a, i8* %ptr.neg
119; CHECK: NoAlias: i8* %ptr.neg, i8* %ptr.shl
120;
121  %a.cmp = icmp sge i64 %a, 0
122  call void @llvm.assume(i1 %a.cmp)
123  %ptr.neg = getelementptr i8, ptr %ptr, i64 -2
124  %ptr.a = getelementptr i8, ptr %ptr, i64 %a
125  %shl = shl nsw i64 %a, 1
126  %ptr.shl = getelementptr i8, ptr %ptr, i64 %shl
127  load i8, ptr %ptr.a
128  load i8, ptr %ptr.neg
129  load i8, ptr %ptr.shl
130  ret void
131}
132
133define void @test5(ptr %ptr, i32 %stride) {
134; CHECK-LABEL: Function: test5: 2 pointers, 1 call sites
135; CHECK-NEXT:    MayAlias:   <6 x double>* %col.ptr.2, <6 x double>* %ptr
136;
137  %gt = icmp sge i32 %stride, 5
138  call void @llvm.assume(i1 %gt)
139  %lv.1 = load <6 x double>, ptr %ptr, align 8
140  %col.ptr.2= getelementptr double, ptr %ptr, i32 %stride
141  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
142  %res.1 = fadd <6 x double> %lv.1, %lv.1
143  %res.2 = fadd <6 x double> %lv.2, %lv.2
144  store <6 x double> %res.1, ptr %ptr, align 8
145  store <6 x double> %res.2, ptr %col.ptr.2, align 8
146  ret void
147}
148
149define void @test6(ptr %ptr, i32 %stride) {
150; CHECK-LABEL: Function: test6: 2 pointers, 1 call sites
151; CHECK-NEXT:    NoAlias:  <6 x double>* %col.ptr.2, <6 x double>* %ptr
152;
153  %gt = icmp sge i32 %stride, 6
154  call void @llvm.assume(i1 %gt)
155  %lv.1 = load <6 x double>, ptr %ptr, align 8
156  %col.ptr.2= getelementptr double, ptr %ptr, i32 %stride
157  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
158  %res.1 = fadd <6 x double> %lv.1, %lv.1
159  %res.2 = fadd <6 x double> %lv.2, %lv.2
160  store <6 x double> %res.1, ptr %ptr, align 8
161  store <6 x double> %res.2, ptr %col.ptr.2, align 8
162  ret void
163}
164
165define void @test7(ptr %ptr, i32 %stride) {
166; CHECK-LABEL: Function: test7: 2 pointers, 1 call sites
167; CHECK-NEXT:    MayAlias: <6 x double>* %col.ptr.2, <6 x double>* %ptr
168;
169  %gt = icmp sge i32 %stride, 0
170  call void @llvm.assume(i1 %gt)
171  %lv.1 = load <6 x double>, ptr %ptr, align 8
172  %col.ptr.2= getelementptr double, ptr %ptr, i32 %stride
173  %lv.2 = load <6 x double>, ptr %col.ptr.2, align 8
174  %res.1 = fadd <6 x double> %lv.1, %lv.1
175  %res.2 = fadd <6 x double> %lv.2, %lv.2
176  store <6 x double> %res.1, ptr %ptr, align 8
177  store <6 x double> %res.2, ptr %col.ptr.2, align 8
178  ret void
179}
180
181declare void @llvm.assume(i1 %cond)
182declare void @barrier()
183