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