1; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,NO-PHI-VALUES 2; RUN: opt < %s -aa-pipeline=basic-aa -passes='require<phi-values>,aa-eval' -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s --check-prefixes=CHECK,PHI-VALUES 3 4; CHECK-LABEL: Function: simple: 5 pointers, 0 call sites 5; CHECK: NoAlias: float* %src1, float* %src2 6; CHECK: NoAlias: float* %phi, float* %src1 7; CHECK: MayAlias: float* %phi, float* %src2 8; CHECK: NoAlias: float* %next, float* %src1 9; CHECK: MayAlias: float* %next, float* %src2 10; CHECK: NoAlias: float* %next, float* %phi 11; CHECK: NoAlias: float* %g, float* %src1 12; CHECK: NoAlias: float* %g, float* %src2 13; CHECK: NoAlias: float* %g, float* %phi 14; CHECK: NoAlias: float* %g, float* %next 15define void @simple(float *%src1, float * noalias %src2, i32 %n) nounwind { 16entry: 17 load float, float* %src1 18 load float, float* %src2 19 br label %loop 20 21loop: 22 %phi = phi float* [ %src2, %entry ], [ %next, %loop ] 23 %idx = phi i32 [ 0, %entry ], [ %idxn, %loop ] 24 %next = getelementptr inbounds float, float* %phi, i32 1 25 %g = getelementptr inbounds float, float* %src1, i32 3 26 %l = load float, float* %phi 27 load float, float* %next 28 %a = fadd float %l, 1.0 29 store float %a, float* %g 30 %idxn = add nsw nuw i32 %idx, 1 31 %cmp5 = icmp eq i32 %idxn, %n 32 br i1 %cmp5, label %end, label %loop 33 34end: 35 ret void 36} 37 38; CHECK-LABEL: Function: notmust: 6 pointers, 0 call sites 39; CHECK: MustAlias: i8* %0, [2 x i32]* %tab 40; CHECK: PartialAlias (off -4): i32* %arrayidx, [2 x i32]* %tab 41; CHECK: NoAlias: i8* %0, i32* %arrayidx 42; CHECK: MustAlias: i32* %arrayidx1, [2 x i32]* %tab 43; CHECK: MustAlias: i8* %0, i32* %arrayidx1 44; CHECK: NoAlias: i32* %arrayidx, i32* %arrayidx1 45; CHECK: MayAlias: i32* %incdec.ptr.i, [2 x i32]* %tab 46; CHECK: NoAlias: i8* %0, i32* %incdec.ptr.i 47; CHECK: MayAlias: i32* %arrayidx, i32* %incdec.ptr.i 48; CHECK: NoAlias: i32* %arrayidx1, i32* %incdec.ptr.i 49; CHECK: MayAlias: i32* %p.addr.05.i, [2 x i32]* %tab 50; CHECK: MayAlias: i8* %0, i32* %p.addr.05.i 51; CHECK: MayAlias: i32* %arrayidx, i32* %p.addr.05.i 52; CHECK: MayAlias: i32* %arrayidx1, i32* %p.addr.05.i 53; CHECK: NoAlias: i32* %incdec.ptr.i, i32* %p.addr.05.i 54define i32 @notmust() nounwind { 55entry: 56 %tab = alloca [2 x i32], align 4 57 %ignore1 = load [2 x i32], [2 x i32]* %tab 58 %0 = bitcast [2 x i32]* %tab to i8* 59 %ignore2 = load i8, i8* %0 60 %arrayidx = getelementptr inbounds [2 x i32], [2 x i32]* %tab, i32 0, i32 1 61 store i32 0, i32* %arrayidx, align 4 62 %arrayidx1 = getelementptr inbounds [2 x i32], [2 x i32]* %tab, i32 0, i32 0 63 store i32 0, i32* %arrayidx1, align 4 64 %1 = add i32 1, 1 65 %cmp4.i = icmp slt i32 %1, 2 66 br i1 %cmp4.i, label %while.body.i, label %f.exit 67 68while.body.i: ; preds = %while.body.i, %entry 69 %2 = phi i32 [ 1, %while.body.i ], [ %1, %entry ] 70 %foo.06.i = phi i32 [ %sub.i, %while.body.i ], [ 2, %entry ] 71 %p.addr.05.i = phi i32* [ %incdec.ptr.i, %while.body.i ], [ %arrayidx1, %entry ] 72 %sub.i = sub nsw i32 %foo.06.i, %2 73 %incdec.ptr.i = getelementptr inbounds i32, i32* %p.addr.05.i, i32 1 74 %ignore3 = load i32, i32* %incdec.ptr.i 75 store i32 %sub.i, i32* %p.addr.05.i, align 4 76 %cmp.i = icmp sgt i32 %sub.i, 1 77 br i1 %cmp.i, label %while.body.i, label %f.exit 78 79f.exit: ; preds = %entry, %while.body.i 80 %3 = load i32, i32* %arrayidx1, align 4 81 %cmp = icmp eq i32 %3, 2 82 %4 = load i32, i32* %arrayidx, align 4 83 %cmp4 = icmp eq i32 %4, 1 84 %or.cond = and i1 %cmp, %cmp4 85 br i1 %or.cond, label %if.end, label %if.then 86 87if.then: ; preds = %f.exit 88 unreachable 89 90if.end: ; preds = %f.exit 91 ret i32 0 92} 93 94; CHECK-LABEL: Function: reverse: 6 pointers, 0 call sites 95; CHECK: MustAlias: i8* %0, [10 x i32]* %tab 96; CHECK: MustAlias: i32* %arrayidx, [10 x i32]* %tab 97; CHECK: MustAlias: i8* %0, i32* %arrayidx 98; CHECK: PartialAlias (off -36): i32* %arrayidx1, [10 x i32]* %tab 99; CHECK: NoAlias: i8* %0, i32* %arrayidx1 100; CHECK: NoAlias: i32* %arrayidx, i32* %arrayidx1 101; CHECK: MayAlias: i32* %incdec.ptr.i, [10 x i32]* %tab 102; CHECK: MayAlias: i8* %0, i32* %incdec.ptr.i 103; CHECK: MayAlias: i32* %arrayidx, i32* %incdec.ptr.i 104; CHECK: MayAlias: i32* %arrayidx1, i32* %incdec.ptr.i 105; CHECK: MayAlias: i32* %p.addr.05.i, [10 x i32]* %tab 106; CHECK: MayAlias: i8* %0, i32* %p.addr.05.i 107; CHECK: MayAlias: i32* %arrayidx, i32* %p.addr.05.i 108; CHECK: MayAlias: i32* %arrayidx1, i32* %p.addr.05.i 109; CHECK: NoAlias: i32* %incdec.ptr.i, i32* %p.addr.05.i 110define i32 @reverse() nounwind { 111entry: 112 %tab = alloca [10 x i32], align 4 113 %ignore1 = load [10 x i32], [10 x i32]* %tab 114 %0 = bitcast [10 x i32]* %tab to i8* 115 %ignore2 = load i8, i8* %0 116 %arrayidx = getelementptr inbounds [10 x i32], [10 x i32]* %tab, i32 0, i32 0 117 store i32 0, i32* %arrayidx, align 4 118 %arrayidx1 = getelementptr inbounds [10 x i32], [10 x i32]* %tab, i32 0, i32 9 119 store i32 0, i32* %arrayidx1, align 4 120 %1 = add i32 1, 1 121 %cmp4.i = icmp slt i32 %1, 2 122 br i1 %cmp4.i, label %while.body.i, label %f.exit 123 124while.body.i: ; preds = %while.body.i, %entry 125 %2 = phi i32 [ 1, %while.body.i ], [ %1, %entry ] 126 %foo.06.i = phi i32 [ %sub.i, %while.body.i ], [ 2, %entry ] 127 %p.addr.05.i = phi i32* [ %incdec.ptr.i, %while.body.i ], [ %arrayidx1, %entry ] 128 %sub.i = sub nsw i32 %foo.06.i, %2 129 %incdec.ptr.i = getelementptr inbounds i32, i32* %p.addr.05.i, i32 -1 130 %ignore3 = load i32, i32* %incdec.ptr.i 131 store i32 %sub.i, i32* %p.addr.05.i, align 4 132 %cmp.i = icmp sgt i32 %sub.i, 1 133 br i1 %cmp.i, label %while.body.i, label %f.exit 134 135f.exit: ; preds = %entry, %while.body.i 136 %3 = load i32, i32* %arrayidx1, align 4 137 %cmp = icmp eq i32 %3, 2 138 %4 = load i32, i32* %arrayidx, align 4 139 %cmp4 = icmp eq i32 %4, 1 140 %or.cond = and i1 %cmp, %cmp4 141 br i1 %or.cond, label %if.end, label %if.then 142 143if.then: ; preds = %f.exit 144 unreachable 145 146if.end: ; preds = %f.exit 147 ret i32 0 148} 149 150; CHECK-LABEL: Function: negative: 5 pointers, 1 call sites 151; CHECK: PartialAlias (off -4): i16* %_tmp1, [3 x i16]* %int_arr.10 152; CHECK: MayAlias: [3 x i16]* %int_arr.10, i16* %ls1.9.0 153; CHECK: MayAlias: i16* %_tmp1, i16* %ls1.9.0 154; CHECK: MayAlias: i16* %_tmp7, [3 x i16]* %int_arr.10 155; CHECK: MayAlias: i16* %_tmp1, i16* %_tmp7 156; CHECK: NoAlias: i16* %_tmp7, i16* %ls1.9.0 157; CHECK: PartialAlias (off -2): i16* %_tmp11, [3 x i16]* %int_arr.10 158; CHECK: NoAlias: i16* %_tmp1, i16* %_tmp11 159; CHECK: MayAlias: i16* %_tmp11, i16* %ls1.9.0 160; CHECK: MayAlias: i16* %_tmp11, i16* %_tmp7 161; CHECK: NoModRef: Ptr: [3 x i16]* %int_arr.10 <-> %_tmp16 = call i16 @call(i32 %_tmp13) 162; CHECK: NoModRef: Ptr: i16* %_tmp1 <-> %_tmp16 = call i16 @call(i32 %_tmp13) 163; CHECK: Both ModRef: Ptr: i16* %ls1.9.0 <-> %_tmp16 = call i16 @call(i32 %_tmp13) 164; CHECK: Both ModRef: Ptr: i16* %_tmp7 <-> %_tmp16 = call i16 @call(i32 %_tmp13) 165; CHECK: NoModRef: Ptr: i16* %_tmp11 <-> %_tmp16 = call i16 @call(i32 %_tmp13) 166define i16 @negative(i16 %argc.5.par) { 167 %int_arr.10 = alloca [3 x i16], align 1 168 load [3 x i16], [3 x i16]* %int_arr.10 169 %_tmp1 = getelementptr inbounds [3 x i16], [3 x i16]* %int_arr.10, i16 0, i16 2 170 load i16, i16* %_tmp1 171 br label %bb1 172 173bb1: ; preds = %bb1, %0 174 %i.7.0 = phi i16 [ 2, %0 ], [ %_tmp5, %bb1 ] 175 %ls1.9.0 = phi i16* [ %_tmp1, %0 ], [ %_tmp7, %bb1 ] 176 store i16 %i.7.0, i16* %ls1.9.0, align 1 177 %_tmp5 = add nsw i16 %i.7.0, -1 178 %_tmp7 = getelementptr i16, i16* %ls1.9.0, i16 -1 179 load i16, i16* %_tmp7 180 %_tmp9 = icmp sgt i16 %i.7.0, 0 181 br i1 %_tmp9, label %bb1, label %bb3 182 183bb3: ; preds = %bb1 184 %_tmp11 = getelementptr inbounds [3 x i16], [3 x i16]* %int_arr.10, i16 0, i16 1 185 %_tmp12 = load i16, i16* %_tmp11, align 1 186 %_tmp13 = sext i16 %_tmp12 to i32 187 %_tmp16 = call i16 @call(i32 %_tmp13) 188 %_tmp18.not = icmp eq i16 %_tmp12, 1 189 br i1 %_tmp18.not, label %bb5, label %bb4 190 191bb4: ; preds = %bb3 192 ret i16 1 193 194bb5: ; preds = %bb3, %bb4 195 ret i16 0 196} 197 198; CHECK-LABEL: Function: dynamic_offset 199; CHECK: NoAlias: i8* %a, i8* %p.base 200; CHECK: MayAlias: i8* %p, i8* %p.base 201; CHECK: NoAlias: i8* %a, i8* %p 202; CHECK: MayAlias: i8* %p.base, i8* %p.next 203; CHECK: NoAlias: i8* %a, i8* %p.next 204; CHECK: MayAlias: i8* %p, i8* %p.next 205define void @dynamic_offset(i1 %c, i8* noalias %p.base) { 206entry: 207 %a = alloca i8 208 load i8, i8* %p.base 209 load i8, i8* %a 210 br label %loop 211 212loop: 213 %p = phi i8* [ %p.base, %entry ], [ %p.next, %loop ] 214 %offset = call i16 @call(i32 0) 215 %p.next = getelementptr inbounds i8, i8* %p, i16 %offset 216 load i8, i8* %p 217 load i8, i8* %p.next 218 br i1 %c, label %loop, label %exit 219 220exit: 221 ret void 222} 223 224; TODO: Currently yields an asymmetric result. 225; CHECK-LABEL: Function: symmetry 226; CHECK: MayAlias: i32* %p, i32* %p.base 227; CHECK: MayAlias: i32* %p.base, i32* %p.next 228; CHECK: NoAlias: i32* %p, i32* %p.next 229; CHECK: MayAlias: i32* %p.base, i32* %result 230; CHECK: NoAlias: i32* %p, i32* %result 231; CHECK: MustAlias: i32* %p.next, i32* %result 232define i32* @symmetry(i32* %p.base, i1 %c) { 233entry: 234 load i32, i32* %p.base 235 br label %loop 236 237loop: 238 %p = phi i32* [ %p.base, %entry ], [ %p.next, %loop ] 239 %p.next = getelementptr inbounds i32, i32* %p, i32 1 240 load i32, i32* %p 241 load i32, i32* %p.next 242 br i1 %c, label %loop, label %exit 243 244exit: 245 %result = phi i32* [ %p.next, %loop ] 246 load i32, i32* %result 247 ret i32* %result 248} 249 250; CHECK-LABEL: Function: nested_loop 251; CHECK: NoAlias: i8* %a, i8* %p.base 252; CHECK: NoAlias: i8* %a, i8* %p.outer 253; NO-PHI-VALUES: MayAlias: i8* %a, i8* %p.inner 254; PHI-VALUES: NoAlias: i8* %a, i8* %p.inner 255; CHECK: NoAlias: i8* %a, i8* %p.inner.next 256; CHECK: NoAlias: i8* %a, i8* %p.outer.next 257define void @nested_loop(i1 %c, i1 %c2, i8* noalias %p.base) { 258entry: 259 %a = alloca i8 260 load i8, i8* %p.base 261 load i8, i8* %a 262 br label %outer_loop 263 264outer_loop: 265 %p.outer = phi i8* [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ] 266 load i8, i8* %p.outer 267 br label %inner_loop 268 269inner_loop: 270 %p.inner = phi i8* [ %p.outer, %outer_loop ], [ %p.inner.next, %inner_loop ] 271 %p.inner.next = getelementptr inbounds i8, i8* %p.inner, i64 1 272 load i8, i8* %p.inner 273 load i8, i8* %p.inner.next 274 br i1 %c, label %inner_loop, label %outer_loop_latch 275 276outer_loop_latch: 277 %p.outer.next = getelementptr inbounds i8, i8* %p.inner, i64 10 278 load i8, i8* %p.outer.next 279 br i1 %c2, label %outer_loop, label %exit 280 281exit: 282 ret void 283} 284 285; Same as the previous test case, but avoiding phi of phi. 286; CHECK-LABEL: Function: nested_loop2 287; CHECK: NoAlias: i8* %a, i8* %p.base 288; CHECK: NoAlias: i8* %a, i8* %p.outer 289; CHECK: NoAlias: i8* %a, i8* %p.outer.next 290; CHECK: MayAlias: i8* %a, i8* %p.inner 291; CHECK: NoAlias: i8* %a, i8* %p.inner.next 292; TODO: (a, p.inner) could be NoAlias 293define void @nested_loop2(i1 %c, i1 %c2, i8* noalias %p.base) { 294entry: 295 %a = alloca i8 296 load i8, i8* %p.base 297 load i8, i8* %a 298 br label %outer_loop 299 300outer_loop: 301 %p.outer = phi i8* [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ] 302 %p.outer.next = getelementptr inbounds i8, i8* %p.outer, i64 10 303 load i8, i8* %p.outer 304 load i8, i8* %p.outer.next 305 br label %inner_loop 306 307inner_loop: 308 %p.inner = phi i8* [ %p.outer.next, %outer_loop ], [ %p.inner.next, %inner_loop ] 309 %p.inner.next = getelementptr inbounds i8, i8* %p.inner, i64 1 310 load i8, i8* %p.inner 311 load i8, i8* %p.inner.next 312 br i1 %c, label %inner_loop, label %outer_loop_latch 313 314outer_loop_latch: 315 br i1 %c2, label %outer_loop, label %exit 316 317exit: 318 ret void 319} 320 321; CHECK-LABEL: Function: nested_loop3 322; CHECK: NoAlias: i8* %a, i8* %p.base 323; CHECK: NoAlias: i8* %a, i8* %p.outer 324; CHECK: NoAlias: i8* %a, i8* %p.outer.next 325; NO-PHI-VALUES: NoAlias: i8* %a, i8* %p.inner 326; PHI-VALUES: MayAlias: i8* %a, i8* %p.inner 327; CHECK: NoAlias: i8* %a, i8* %p.inner.next 328define void @nested_loop3(i1 %c, i1 %c2, i8* noalias %p.base) { 329entry: 330 %a = alloca i8 331 load i8, i8* %p.base 332 load i8, i8* %a 333 br label %outer_loop 334 335outer_loop: 336 %p.outer = phi i8* [ %p.base, %entry ], [ %p.outer.next, %outer_loop_latch ] 337 %p.outer.next = getelementptr inbounds i8, i8* %p.outer, i64 10 338 load i8, i8* %p.outer 339 load i8, i8* %p.outer.next 340 br label %inner_loop 341 342inner_loop: 343 %p.inner = phi i8* [ %p.outer, %outer_loop ], [ %p.inner.next, %inner_loop ] 344 %p.inner.next = getelementptr inbounds i8, i8* %p.inner, i64 1 345 load i8, i8* %p.inner 346 load i8, i8* %p.inner.next 347 br i1 %c, label %inner_loop, label %outer_loop_latch 348 349outer_loop_latch: 350 br i1 %c2, label %outer_loop, label %exit 351 352exit: 353 ret void 354} 355 356; CHECK-LABEL: Function: sibling_loop 357; CHECK: NoAlias: i8* %a, i8* %p.base 358; CHECK: NoAlias: i8* %a, i8* %p1 359; CHECK: NoAlias: i8* %a, i8* %p1.next 360; CHECK: MayAlias: i8* %a, i8* %p2 361; CHECK: NoAlias: i8* %a, i8* %p2.next 362; TODO: %p2 does not alias %a 363define void @sibling_loop(i1 %c, i1 %c2, i8* noalias %p.base) { 364entry: 365 %a = alloca i8 366 load i8, i8* %p.base 367 load i8, i8* %a 368 br label %loop1 369 370loop1: 371 %p1 = phi i8* [ %p.base, %entry ], [ %p1.next, %loop1 ] 372 %p1.next = getelementptr inbounds i8, i8* %p1, i64 10 373 load i8, i8* %p1 374 load i8, i8* %p1.next 375 br i1 %c, label %loop1, label %loop2 376 377loop2: 378 %p2 = phi i8* [ %p1.next, %loop1 ], [ %p2.next, %loop2 ] 379 %p2.next = getelementptr inbounds i8, i8* %p2, i64 1 380 load i8, i8* %p2 381 load i8, i8* %p2.next 382 br i1 %c2, label %loop2, label %exit 383 384exit: 385 ret void 386} 387 388; CHECK-LABEL: Function: sibling_loop2 389; CHECK: NoAlias: i8* %a, i8* %p.base 390; CHECK: NoAlias: i8* %a, i8* %p1 391; CHECK: NoAlias: i8* %a, i8* %p1.next 392; NO-PHI-VALUES: NoAlias: i8* %a, i8* %p2 393; PHI-VALUES: MayAlias: i8* %a, i8* %p2 394; CHECK: NoAlias: i8* %a, i8* %p2.next 395define void @sibling_loop2(i1 %c, i1 %c2, i8* noalias %p.base) { 396entry: 397 %a = alloca i8 398 load i8, i8* %p.base 399 load i8, i8* %a 400 br label %loop1 401 402loop1: 403 %p1 = phi i8* [ %p.base, %entry ], [ %p1.next, %loop1 ] 404 %p1.next = getelementptr inbounds i8, i8* %p1, i64 10 405 load i8, i8* %p1 406 load i8, i8* %p1.next 407 br i1 %c, label %loop1, label %loop2 408 409loop2: 410 %p2 = phi i8* [ %p1, %loop1 ], [ %p2.next, %loop2 ] 411 %p2.next = getelementptr inbounds i8, i8* %p2, i64 1 412 load i8, i8* %p2 413 load i8, i8* %p2.next 414 br i1 %c2, label %loop2, label %exit 415 416exit: 417 ret void 418} 419 420declare i16 @call(i32) 421