diff --git a/llvm/lib/Analysis/BasicAliasAnalysis.cpp b/llvm/lib/Analysis/BasicAliasAnalysis.cpp --- a/llvm/lib/Analysis/BasicAliasAnalysis.cpp +++ b/llvm/lib/Analysis/BasicAliasAnalysis.cpp @@ -1779,6 +1779,16 @@ if (!Inst) return true; + // Check if the value is itself a PHI node that is reachable from itself, + // implying a cycle that can cause the value to have a different value on + // different iterations. In this case, return false to indicate that we cannot + // prove the two values will be equal across cycles. + if (const PHINode *PN = dyn_cast(Inst)) { + if (isPotentiallyReachable(PN->getParent(), PN->getParent(), nullptr, DT)) { + return false; + } + } + if (VisitedPhiBBs.empty()) return true; diff --git a/llvm/test/Analysis/BasicAA/value-equal-cycle-phi.ll b/llvm/test/Analysis/BasicAA/value-equal-cycle-phi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/BasicAA/value-equal-cycle-phi.ll @@ -0,0 +1,40 @@ +; RUN: opt -aa-pipeline=basic-aa -passes=aa-eval -print-all-alias-modref-info -disable-output < %s 2>&1 | FileCheck %s + +; CHECK-LABEL: may_alias_ptr +; CHECK: MayAlias: float* %p, float* %p.1 + +define void @may_alias_ptr(float* %arr, float* %out, i32* %idx) local_unnamed_addr { +entry: + br label %header + +header: + %i = phi i32 [ 0, %entry ], [ %i.next, %latch ] + %p.3 = getelementptr i32, i32* %idx, i32 %i + %t = load i32, i32* %p.3, align 4 + %a = icmp eq i32 %t, 0 + br i1 %a, label %if.then, label %if.else + +if.then: + ; BasicAA cannot know whether the prior iteration wrote to arr[i], so it must + ; return MayAlias between %p and %p.1. + %p = getelementptr inbounds float, float* %arr, i32 %i + %v = load float, float* %p, align 4 + %p.2 = getelementptr inbounds float, float* %out, i32 0 + store float %v, float* %p.2, align 4 + br label %latch + +if.else: + ; This will write to arr[i+1], which will be arr[i] on the next iteration + %i.0 = add nuw nsw i32 %i, 1 + %p.1 = getelementptr float, float* %arr, i32 %i.0 + store float 0.0, float* %p.1, align 4 + br label %latch + +latch: + %i.next = add nuw nsw i32 %i, 1 + %c = icmp ult i32 %i.next, 4 + br i1 %c, label %header, label %exit + +exit: + ret void +}