1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s 2 3%struct.S = type { i32, [2 x i32], i32 } 4%struct.S2 = type { i32, [4 x i32], [4 x i32] } 5@G = global [10 x i32] zeroinitializer, align 4 6 7; CHECK: Function: t1 8; CHECK: NoAlias: i32* %gep1, i32* %gep2 9define void @t1(ptr %s) { 10 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 1 11 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 0 12 load i32, ptr %gep1 13 load i32, ptr %gep2 14 ret void 15} 16 17; CHECK: Function: t2_fwd 18; CHECK: MayAlias: i32* %gep1, i32* %gep2 19define void @t2_fwd(ptr %s, ptr %q) { 20 %in_array = load i32, ptr %q, !range !0 21 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 22 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 0 23 load i32, ptr %gep1 24 load i32, ptr %gep2 25 ret void 26} 27 28; CHECK: Function: t2_rev 29; CHECK: MayAlias: i32* %gep1, i32* %gep2 30define void @t2_rev(ptr %s, ptr %q) { 31 %in_array = load i32, ptr %q, !range !0 32 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 0 33 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 34 load i32, ptr %gep1 35 load i32, ptr %gep2 36 ret void 37} 38 39; CHECK: Function: t3_fwd 40; CHECK: NoAlias: i32* %gep1, i32* %gep2 41define void @t3_fwd(ptr %s, ptr %q) { 42 %knownzero = load i32, ptr %q, !range !1 43 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %knownzero 44 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 1 45 load i32, ptr %gep1 46 load i32, ptr %gep2 47 ret void 48} 49 50; CHECK: Function: t3_rev 51; CHECK: NoAlias: i32* %gep1, i32* %gep2 52define void @t3_rev(ptr %s, ptr %q) { 53 %knownzero = load i32, ptr %q, !range !1 54 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 1 55 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %knownzero 56 load i32, ptr %gep1 57 load i32, ptr %gep2 58 ret void 59} 60 61; CHECK: Function: member_after 62; CHECK: NoAlias: i32* %gep1, i32* %gep2 63define void @member_after(ptr %s, ptr %q) { 64 %in_array = load i32, ptr %q, !range !0 65 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 66 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2 67 load i32, ptr %gep1 68 load i32, ptr %gep2 69 ret void 70} 71 72; CHECK: Function: member_after_rev 73; CHECK: NoAlias: i32* %gep1, i32* %gep2 74define void @member_after_rev(ptr %s, ptr %q) { 75 %in_array = load i32, ptr %q, !range !0 76 %gep2 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 2 77 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 78 load i32, ptr %gep1 79 load i32, ptr %gep2 80 ret void 81} 82 83; CHECK: Function: member_before 84; CHECK: NoAlias: i32* %gep1, i32* %s 85define void @member_before(ptr %s, ptr %q) { 86 %in_array = load i32, ptr %q, !range !0 87 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 88 load i32, ptr %gep1 89 load i32, ptr %s 90 ret void 91} 92 93; CHECK: Function: member_before_rev 94; CHECK: NoAlias: i32* %gep1, i32* %s 95define void @member_before_rev(ptr %s, ptr %q) { 96 %in_array = load i32, ptr %q, !range !0 97 %gep1 = getelementptr inbounds %struct.S, ptr %s, i64 0, i32 1, i32 %in_array 98 load i32, ptr %gep1 99 load i32, ptr %s 100 ret void 101} 102 103; CHECK-LABEL: Function: t5 104; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 105; CHECK: PartialAlias (off -4): i32* %gep2, %struct.S2* %s 106; CHECK: NoAlias: i32* %gep1, i32* %gep2 107define void @t5(ptr %s, ptr %q) { 108 %in_array = load i32, ptr %q, !range !3 109 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 %in_array 110 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 1, i32 0 111 load %struct.S2, ptr %s 112 load i32, ptr %gep1 113 load i32, ptr %gep2 114 ret void 115} 116 117; CHECK-LABEL: Function: t6 118; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 119; CHECK: PartialAlias (off -16): i32* %gep2, %struct.S2* %s 120; CHECK: MayAlias: i32* %gep1, i32* %gep2 121define void @t6(ptr %s, ptr %q) { 122 %in_array = load i32, ptr %q, !range !3 123 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 %in_array 124 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 1, i32 3 125 load %struct.S2, ptr %s 126 load i32, ptr %gep1 127 load i32, ptr %gep2 128 ret void 129} 130 131; CHECK-LABEL: Function: t7 132; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 133; CHECK: PartialAlias (off -20): i32* %gep2, %struct.S2* %s 134; CHECK: NoAlias: i32* %gep1, i32* %gep2 135define void @t7(ptr %s, ptr %q) { 136 %in_array = load i32, ptr %q, !range !4 137 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 %in_array 138 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 0 139 load %struct.S2, ptr %s 140 load i32, ptr %gep1 141 load i32, ptr %gep2 142 ret void 143} 144 145; CHECK-LABEL: Function: t8 146; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 147; CHECK: PartialAlias (off -24): i32* %gep2, %struct.S2* %s 148; CHECK: MayAlias: i32* %gep1, i32* %gep2 149define void @t8(ptr %s, ptr %q) { 150 %in_array = load i32, ptr %q, !range !4 151 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 %in_array 152 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 1 153 load %struct.S2, ptr %s 154 load i32, ptr %q 155 load i32, ptr %gep1 156 load i32, ptr %gep2 157 ret void 158} 159 160; CHECK-LABEL: Function: t9 161; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 162; CHECK: PartialAlias (off -20): i32* %gep2, %struct.S2* %s 163; CHECK: NoAlias: i32* %gep1, i32* %gep2 164define void @t9(ptr %s, ptr %q) { 165 %in_array = load i32, ptr %q, !range !5 166 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 1, i32 %in_array 167 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 0 168 load %struct.S2, ptr %s 169 load i32, ptr %gep1 170 load i32, ptr %gep2 171 ret void 172} 173 174; CHECK-LABEL: Function: t10 175; CHECK: MayAlias: i32* %gep1, %struct.S2* %s 176; CHECK: PartialAlias (off -4): i32* %gep2, %struct.S2* %s 177; CHECK: MayAlias: i32* %gep1, i32* %gep2 178define void @t10(ptr %s, ptr %q) { 179 %in_array = load i32, ptr %q, !range !5 180 %gep1 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 2, i32 %in_array 181 %gep2 = getelementptr inbounds %struct.S2, ptr %s, i64 0, i32 1, i32 0 182 load %struct.S2, ptr %s 183 load i32, ptr %gep1 184 load i32, ptr %gep2 185 ret void 186} 187 188; CHECK-LABEL: Function: zeroext_index 189; CHECK: MayAlias: i32* %gep, [256 x i32]* %s 190define void @zeroext_index(ptr %s, ptr %q) { 191 %a = load i8, ptr %q, !range !6 192 %in_array = zext i8 %a to i32 193 %gep = getelementptr inbounds [256 x i32], ptr %s, i64 0, i32 %in_array 194 load [256 x i32], ptr %s 195 load i32, ptr %gep 196 ret void 197} 198 199; CHECK-LABEL: Function: multiple 200; CHECK: MayAlias: i32* %p, i32* %p.01 201; CHECK: MayAlias: i32* %p, i32* %p.02 202; CHECK: MayAlias: i32* %p.01, i32* %p.02 203; CHECK: NoAlias: i32* %p.01, i32* %p.2 204; CHECK: MayAlias: i32* %p.02, i32* %p.2 205; CHECK: NoAlias: i32* %p.01, i32* %p.3 206; CHECK: NoAlias: i32* %p.02, i32* %p.3 207define void @multiple(ptr %p, ptr %o1_ptr, ptr %o2_ptr) { 208 %o1 = load i32, ptr %o1_ptr, !range !0 209 %o2 = load i32, ptr %o2_ptr, !range !0 210 %p.01 = getelementptr i32, ptr %p, i32 %o1 ; p + [0, 1] 211 %p.02 = getelementptr i32, ptr %p.01, i32 %o2 ; p + [0, 2] 212 %p.2 = getelementptr i32, ptr %p, i32 2 213 %p.3 = getelementptr i32, ptr %p, i32 3 214 load i32, ptr %p 215 load i32, ptr %p.01 216 load i32, ptr %p.02 217 load i32, ptr %p.2 218 load i32, ptr %p.3 219 ret void 220} 221 222; p.neg1 and p.o.1 don't alias, even though the addition o+1 may overflow. 223; While it makes INT_MIN a possible offset, offset -1 is not possible. 224; CHECK-LABEL: Function: benign_overflow 225; CHECK: MayAlias: i8* %p, i8* %p.o 226; CHECK: MayAlias: i8* %p.neg1, i8* %p.o 227; CHECK: MayAlias: i8* %p, i8* %p.o.1 228; CHECK: NoAlias: i8* %p.neg1, i8* %p.o.1 229; CHECK: NoAlias: i8* %p.o, i8* %p.o.1 230define void @benign_overflow(ptr %p, i64 %o) { 231 %c = icmp sge i64 %o, -1 232 call void @llvm.assume(i1 %c) 233 %p.neg1 = getelementptr i8, ptr %p, i64 -1 234 %p.o = getelementptr i8, ptr %p, i64 %o 235 %p.o.1 = getelementptr i8, ptr %p.o, i64 1 236 load i8, ptr %p 237 load i8, ptr %p.neg1 238 load i8, ptr %p.o 239 load i8, ptr %p.o.1 240 ret void 241} 242 243; CHECK-LABEL: pr63266 244; CHECK: MayAlias: i8* %gep2, i8* %offset16 245define void @pr63266(i1 %c, ptr %base) { 246entry: 247 %offset16 = getelementptr inbounds i8, ptr %base, i64 16 248 %gep1 = getelementptr i8, ptr %base, i64 -9223372036854775792 249 br i1 %c, label %if, label %join 250 251if: 252 br label %join 253 254join: 255 %phi = phi i64 [ -9223372036854775808, %if ], [ 0, %entry ] 256 %gep2 = getelementptr i8, ptr %gep1, i64 %phi 257 store i8 0, ptr %gep2 258 load i8, ptr %offset16 259 ret void 260} 261 262 263; CHECK-LABEL: Function: select_in_gep 264; CHECK: NoAlias: i32* %arrayidx, i32* getelementptr inbounds ([10 x i32], ptr @G, i64 0, i64 3) 265define i32 @select_in_gep(i1 %c) { 266entry: 267 %select_ = select i1 %c, i64 2, i64 1 268 %arrayidx = getelementptr inbounds [10 x i32], ptr @G, i64 0, i64 %select_ 269 store i32 42, ptr %arrayidx, align 4 270 %load_ = load i32, ptr getelementptr inbounds ([10 x i32], ptr @G, i64 0, i64 3), align 4 271 ret i32 %load_ 272} 273 274declare void @llvm.assume(i1) 275 276!0 = !{ i32 0, i32 2 } 277!1 = !{ i32 0, i32 1 } 278!2 = !{ i32 1, i32 2 } 279!3 = !{ i32 -2, i32 0 } 280!4 = !{ i32 1, i32 536870911 } 281!5 = !{ i32 -536870911, i32 4 } 282!6 = !{ i8 -2, i8 0 } 283