| ; RUN: opt < %s -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output 2>&1 | FileCheck %s | |
| target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128" | |
| target triple = "x86_64-unknown-linux-gnu" | |
| ; rdar://7282591 | |
| @X = common global i32 0 | |
| @Y = common global i32 0 | |
| @Z = common global i32 0 | |
| ; CHECK-LABEL: foo | |
| ; CHECK: NoAlias: i32* %P, i32* @Z | |
| define void @foo(i32 %cond) nounwind { | |
| entry: | |
| %"alloca point" = bitcast i32 0 to i32 | |
| %tmp = icmp ne i32 %cond, 0 | |
| br i1 %tmp, label %bb, label %bb1 | |
| bb: | |
| br label %bb2 | |
| bb1: | |
| br label %bb2 | |
| bb2: | |
| %P = phi ptr [ @X, %bb ], [ @Y, %bb1 ] | |
| %tmp1 = load i32, ptr @Z, align 4 | |
| store i32 123, ptr %P, align 4 | |
| %tmp2 = load i32, ptr @Z, align 4 | |
| br label %return | |
| return: | |
| ret void | |
| } | |
| ; Pointers can vary in between iterations of loops. | |
| ; PR18068 | |
| ; CHECK-LABEL: pr18068 | |
| ; CHECK: MayAlias: i32* %0, i32* %arrayidx5 | |
| ; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5 | |
| define i32 @pr18068(ptr %jj7, ptr %j) { | |
| entry: | |
| %oa5 = alloca [100 x i32], align 16 | |
| br label %codeRepl | |
| codeRepl: | |
| %0 = phi ptr [ %arrayidx13, %for.body ], [ %j, %entry ] | |
| %targetBlock = call i1 @cond(ptr %jj7) | |
| br i1 %targetBlock, label %for.body, label %bye | |
| for.body: | |
| %1 = load i32, ptr %jj7, align 4 | |
| %idxprom4 = zext i32 %1 to i64 | |
| %arrayidx5 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i64 %idxprom4 | |
| %2 = load i32, ptr %arrayidx5, align 4 | |
| %sub6 = sub i32 %2, 6 | |
| store i32 %sub6, ptr %arrayidx5, align 4 | |
| ; %0 and %arrayidx5 can alias! It is not safe to DSE the above store. | |
| %3 = load i32, ptr %0, align 4 | |
| store i32 %3, ptr %arrayidx5, align 4 | |
| %sub11 = add i32 %1, -1 | |
| %idxprom12 = zext i32 %sub11 to i64 | |
| %arrayidx13 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i64 %idxprom12 | |
| load i32, ptr %arrayidx13 | |
| call void @inc(ptr %jj7) | |
| br label %codeRepl | |
| bye: | |
| %.reload = load i32, ptr %jj7, align 4 | |
| ret i32 %.reload | |
| } | |
| declare i1 @cond(ptr) | |
| declare void @inc(ptr) | |
| ; When we have a chain of phis in nested loops we should recognise if there's | |
| ; actually only one underlying value. | |
| ; FIXME: All of these could be NoAlias. | |
| ; CHECK-LABEL: loop_phi_chain | |
| ; CHECK: MayAlias: i32* %val1, i32* @Y | |
| ; CHECK: MayAlias: i32* %val2, i32* @Y | |
| ; CHECK: MayAlias: i32* %val3, i32* @Y | |
| define void @loop_phi_chain(i32 %a, i32 %b, i32 %c) { | |
| entry: | |
| br label %loop1 | |
| loop1: | |
| %n1 = phi i32 [ 0, %entry ], [ %add1, %loop2 ] | |
| %val1 = phi ptr [ @X, %entry ], [ %val2, %loop2 ] | |
| load i32, ptr %val1 | |
| %add1 = add i32 %n1, 1 | |
| %cmp1 = icmp ne i32 %n1, 32 | |
| br i1 %cmp1, label %loop2, label %end | |
| loop2: | |
| %n2 = phi i32 [ 0, %loop1 ], [ %add2, %loop3 ] | |
| %val2 = phi ptr [ %val1, %loop1 ], [ %val3, %loop3 ] | |
| load i32, ptr %val2 | |
| %add2 = add i32 %n2, 1 | |
| %cmp2 = icmp ne i32 %n2, 32 | |
| br i1 %cmp2, label %loop3, label %loop1 | |
| loop3: | |
| %n3 = phi i32 [ 0, %loop2 ], [ %add3, %loop3 ] | |
| %val3 = phi ptr [ %val2, %loop2 ], [ %val3, %loop3 ] | |
| store i32 0, ptr %val3, align 4 | |
| store i32 0, ptr @Y, align 4 | |
| %add3 = add i32 %n3, 1 | |
| %cmp3 = icmp ne i32 %n3, 32 | |
| br i1 %cmp3, label %loop3, label %loop2 | |
| end: | |
| ret void | |
| } | |
| ; CHECK-LABEL: phi_and_select | |
| ; CHECK: MustAlias: i32* %p, i32* %s | |
| define void @phi_and_select(i1 %c, i1 %c2, ptr %x, ptr %y) { | |
| entry: | |
| br i1 %c, label %true, label %false | |
| true: | |
| br label %exit | |
| false: | |
| br label %exit | |
| exit: | |
| %p = phi ptr [ %x, %true ], [ %y, %false ] | |
| %s = select i1 %c2, ptr %p, ptr %p | |
| store i32 0, ptr %p | |
| store i32 0, ptr %s | |
| ret void | |
| } | |
| ; CHECK-LABEL: phi_and_phi_cycle | |
| ; CHECK: NoAlias: i32* %p1, i32* %p2 | |
| define void @phi_and_phi_cycle(ptr noalias %x, ptr noalias %y) { | |
| entry: | |
| br label %loop | |
| loop: | |
| %p1 = phi ptr [ %x, %entry ], [ %p1.next, %loop ] | |
| %p2 = phi ptr [ %y, %entry ], [ %p2.next, %loop ] | |
| %p1.next = getelementptr i32, ptr %p1, i64 1 | |
| %p2.next = getelementptr i32, ptr %p1, i64 2 | |
| store i32 0, ptr %p1 | |
| store i32 0, ptr %p2 | |
| br label %loop | |
| } | |
| ; CHECK-LABEL: phi_and_gep_unknown_size | |
| ; CHECK: NoModRef: call void @llvm.memset.p0.i32(ptr %g, i8 0, i32 %size, i1 false) <-> call void @llvm.memset.p0.i32(ptr %z, i8 0, i32 %size, i1 false) | |
| define void @phi_and_gep_unknown_size(i1 %c, ptr %x, ptr %y, ptr noalias %z, i32 %size) { | |
| entry: | |
| br i1 %c, label %true, label %false | |
| true: | |
| br label %exit | |
| false: | |
| br label %exit | |
| exit: | |
| %p = phi ptr [ %x, %true ], [ %y, %false ] | |
| %g = getelementptr inbounds i8, ptr %p, i64 1 | |
| call void @llvm.memset.p0.i32(ptr %g, i8 0, i32 %size, i1 false) | |
| call void @llvm.memset.p0.i32(ptr %z, i8 0, i32 %size, i1 false) | |
| ret void | |
| } | |
| ; If a phi arm is the other pointer, the gep may alias it. | |
| ; CHECK-LABEL: phi_and_gep_unknown_size_may | |
| ; CHECK: MayAlias: i8* %g, i8* %z | |
| define void @phi_and_gep_unknown_size_may(i1 %c, ptr %x, ptr %z) { | |
| entry: | |
| br i1 %c, label %true, label %false | |
| true: | |
| br label %exit | |
| false: | |
| br label %exit | |
| exit: | |
| %p = phi ptr [ %x, %true ], [ %z, %false ] | |
| %g = getelementptr inbounds i8, ptr %p, i64 1 | |
| store i8 0, ptr %g | |
| store i8 0, ptr %z | |
| ret void | |
| } | |
| declare void @llvm.memset.p0.i32(ptr, i8, i32, i1) | |
| ; CHECK-LABEL: unsound_inequality | |
| ; CHECK: MayAlias: i32* %arrayidx5, i32* %phi | |
| ; CHECK: MayAlias: i32* %arrayidx13, i32* %phi | |
| ; CHECK: NoAlias: i32* %arrayidx13, i32* %arrayidx5 | |
| ; When recursively reasoning about phis, we can't use predicates between | |
| ; two values as we might be comparing the two from different iterations. | |
| define i32 @unsound_inequality(ptr %jj7, ptr %j) { | |
| entry: | |
| %oa5 = alloca [100 x i32], align 16 | |
| br label %for.body | |
| for.body: ; preds = %for.body, %entry | |
| %phi = phi ptr [ %arrayidx13, %for.body ], [ %j, %entry ] | |
| load i32, ptr %phi | |
| %idx = load i32, ptr %jj7, align 4 | |
| %arrayidx5 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i32 %idx | |
| store i32 0, ptr %arrayidx5, align 4 | |
| store i32 0, ptr %phi, align 4 | |
| %notequal = add i32 %idx, 1 | |
| %arrayidx13 = getelementptr inbounds [100 x i32], ptr %oa5, i64 0, i32 %notequal | |
| store i32 0, ptr %arrayidx13, align 4 | |
| br label %for.body | |
| } | |
| ; CHECK-LABEL: single_arg_phi | |
| ; CHECK: NoAlias: i32* %ptr, i32* %ptr.next | |
| ; CHECK: MustAlias: i32* %ptr, i32* %ptr.phi | |
| ; CHECK: MustAlias: i32* %ptr.next, i32* %ptr.next.phi | |
| define void @single_arg_phi(ptr %ptr.base) { | |
| entry: | |
| br label %loop | |
| loop: | |
| %ptr = phi ptr [ %ptr.base, %entry ], [ %ptr.next, %split ] | |
| %ptr.next = getelementptr inbounds i32, ptr %ptr, i64 1 | |
| load i32, ptr %ptr | |
| load i32, ptr %ptr.next | |
| br label %split | |
| split: | |
| %ptr.phi = phi ptr [ %ptr, %loop ] | |
| %ptr.next.phi = phi ptr [ %ptr.next, %loop ] | |
| load i32, ptr %ptr.phi | |
| load i32, ptr %ptr.next.phi | |
| br label %loop | |
| } | |
| ; CHECK-LABEL: phi_of_geps_based_on_alloca | |
| ; CHECK: NoAlias: i32* %gep3, i32* %phi | |
| define void @phi_of_geps_based_on_alloca(i1 %c) { | |
| %a = alloca [3 x i32] | |
| br i1 %c, label %if, label %else | |
| if: | |
| %gep1 = getelementptr i32, ptr %a, i64 1 | |
| br label %join | |
| else: | |
| %gep2 = getelementptr i32, ptr %a, i64 2 | |
| br label %join | |
| join: | |
| %phi = phi ptr [ %gep1, %if ], [ %gep2, %else ] | |
| %gep3 = getelementptr i32, ptr %a, i64 3 | |
| load i32, ptr %phi | |
| load i32, ptr %gep3 | |
| ret void | |
| } | |
| ; Don't crash with an unreachable predecessor. | |
| ; CHECK-LABEL: pr59360 | |
| ; CHECK: MayAlias: i32* %loaded.ptr, i32* %phi | |
| define void @pr59360() { | |
| entry: | |
| br label %outer | |
| loopexit: ; No predecessors! | |
| br label %outer | |
| outer: ; preds = %loopexit, %entry | |
| %phi = phi ptr [ %loaded.ptr, %loopexit ], [ null, %entry ] | |
| store i32 0, ptr %phi, align 4 | |
| %loaded.ptr = load ptr, ptr null, align 8 | |
| %0 = load i32, ptr %loaded.ptr, align 4 | |
| ret void | |
| } |