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