diff --git a/llvm/include/llvm/Analysis/MemorySSA.h b/llvm/include/llvm/Analysis/MemorySSA.h --- a/llvm/include/llvm/Analysis/MemorySSA.h +++ b/llvm/include/llvm/Analysis/MemorySSA.h @@ -1217,7 +1217,18 @@ private: void fillInCurrentPair() { CurrentPair.first = *DefIterator; - if (WalkingPhi && Location.Ptr) { + auto HasTrivialCycle = [](auto Def) { + BasicBlock *DefBlock = Def->getBlock(); + auto *DefPhi = dyn_cast(Def); + return DefPhi && + any_of(DefPhi->blocks(), [DefBlock](BasicBlock *IncomingBlock) { + return DefBlock == IncomingBlock; + }); + }; + // Using a phi-translated address is only safe if the PHI is not part of a + // cycle. Otherwise we only check the address accessed in the first visit of + // the cycle. + if (WalkingPhi && Location.Ptr && !HasTrivialCycle(OriginalAccess)) { PHITransAddr Translator( const_cast(Location.Ptr), OriginalAccess->getBlock()->getModule()->getDataLayout(), nullptr); diff --git a/llvm/test/Analysis/MemorySSA/phi-translation-cycle.ll b/llvm/test/Analysis/MemorySSA/phi-translation-cycle.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Analysis/MemorySSA/phi-translation-cycle.ll @@ -0,0 +1,45 @@ +; RUN: opt -basicaa -tbaa -print-memoryssa -verify-memoryssa -analyze < %s 2>&1 | FileCheck %s --check-prefixes=CHECK +; RUN: opt -aa-pipeline=basic-aa,type-based-aa -passes='print,verify' -disable-output < %s 2>&1 | FileCheck %s --check-prefixes=CHECK + +; Test case for PR46156. Make sure phi translation is skipped for cyclic phis. + +@c = local_unnamed_addr global [2 x i16] zeroinitializer, align 2 + +define i32 @test1(i32* noalias %ptr) { +; CHECK-LABEL: define i32 @test1 +; CHECK-LABEL: entry: +; CHECK: ; 1 = MemoryDef(liveOnEntry) +; CHECK-NEXT: store i16 1, i16* %s1.ptr, align 2 + +; CHECK-LABEL: %for.body +; CHECK: ; MemoryUse(1) MayAlias +; CHECK-NEXT: %lv = load i16, i16* %arrayidx, align 2, !tbaa !0 + +entry: + %s1.ptr = getelementptr inbounds [2 x i16], [2 x i16]* @c, i64 0, i64 0 + store i16 1, i16* %s1.ptr, align 2, !tbaa !0 + br label %for.body + +for.body: ; preds = %for.body, %entry + %storemerge2 = phi i32 [ 1, %entry ], [ %dec, %for.body ] + %idxprom1 = zext i32 %storemerge2 to i64 + %arrayidx = getelementptr inbounds [2 x i16], [2 x i16]* @c, i64 0, i64 %idxprom1 + %lv = load i16, i16* %arrayidx, align 2, !tbaa !0 + %conv = sext i16 %lv to i32 + store i32 %conv, i32* %ptr, align 4, !tbaa !4 + %dec = add nsw i32 %storemerge2, -1 + %cmp = icmp sgt i32 %storemerge2, 0 + br i1 %cmp, label %for.body, label %for.end + +for.end: ; preds = %for.body + %s2.ptr = getelementptr inbounds [2 x i16], [2 x i16]* @c, i64 0, i64 0 + store i16 0, i16* %s2.ptr, align 2, !tbaa !0 + ret i32 0 +} + +!0 = !{!1, !1, i64 0} +!1 = !{!"short", !2, i64 0} +!2 = !{!"omnipotent char", !3, i64 0} +!3 = !{!"Simple C/C++ TBAA"} +!4 = !{!5, !5, i64 0} +!5 = !{!"int", !2, i64 0}