Index: llvm/lib/Analysis/MemorySSA.cpp =================================================================== --- llvm/lib/Analysis/MemorySSA.cpp +++ llvm/lib/Analysis/MemorySSA.cpp @@ -282,7 +282,6 @@ // clobbers where they don't really exist at all. Please see D43269 for // context. switch (II->getIntrinsicID()) { - case Intrinsic::lifetime_end: case Intrinsic::invariant_start: case Intrinsic::invariant_end: case Intrinsic::assume: @@ -359,22 +358,6 @@ } // end anonymous namespace -static bool lifetimeEndsAt(MemoryDef *MD, const MemoryLocation &Loc, - BatchAAResults &AA) { - Instruction *Inst = MD->getMemoryInst(); - if (IntrinsicInst *II = dyn_cast(Inst)) { - switch (II->getIntrinsicID()) { - case Intrinsic::lifetime_end: { - MemoryLocation ArgLoc = MemoryLocation::getAfter(II->getArgOperand(1)); - return AA.alias(ArgLoc, Loc) == MustAlias; - } - default: - return false; - } - } - return false; -} - template static bool isUseTriviallyOptimizableToLiveOnEntry(AliasAnalysisType &AA, const Instruction *I) { @@ -1466,15 +1449,6 @@ } MemoryDef *MD = cast(VersionStack[UpperBound]); - // If the lifetime of the pointer ends at this instruction, it's live on - // entry. - if (!UseMLOC.IsCall && lifetimeEndsAt(MD, UseMLOC.getLoc(), *AA)) { - // Reset UpperBound to liveOnEntryDef's place in the stack - UpperBound = 0; - FoundClobberResult = true; - LocInfo.AR = MustAlias; - break; - } ClobberAlias CA = instructionClobbersQuery(MD, MU, UseMLOC, *AA); if (CA.IsClobber) { FoundClobberResult = true; Index: llvm/test/Analysis/MemorySSA/lifetime-simple.ll =================================================================== --- llvm/test/Analysis/MemorySSA/lifetime-simple.ll +++ llvm/test/Analysis/MemorySSA/lifetime-simple.ll @@ -1,8 +1,7 @@ ; RUN: opt -basic-aa -print-memoryssa -verify-memoryssa -enable-new-pm=0 -analyze < %s 2>&1 | FileCheck %s ; RUN: opt -aa-pipeline=basic-aa -passes='print,verify' -disable-output < %s 2>&1 | FileCheck %s -; This test checks a number of things: -; First, the lifetime markers should not clobber any uses of Q or P. -; Second, the loads of P are MemoryUse(LiveOnEntry) due to the placement of the markers vs the loads. +; This test checks that lifetime markers are considered clobbers of %P, +; and due to lack of noalias information, of %Q as well. define i8 @test(i8* %P, i8* %Q) { entry: @@ -18,10 +17,10 @@ ; CHECK: 3 = MemoryDef(2) ; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 32, i8* %P) call void @llvm.lifetime.end.p0i8(i64 32, i8* %P) -; CHECK: MemoryUse(liveOnEntry) +; CHECK: MemoryUse(3) ; CHECK-NEXT: %1 = load i8, i8* %P %1 = load i8, i8* %P -; CHECK: MemoryUse(2) +; CHECK: MemoryUse(3) ; CHECK-NEXT: %2 = load i8, i8* %Q %2 = load i8, i8* %Q ret i8 %1 Index: llvm/test/Transforms/MemCpyOpt/lifetime.ll =================================================================== --- llvm/test/Transforms/MemCpyOpt/lifetime.ll +++ llvm/test/Transforms/MemCpyOpt/lifetime.ll @@ -1,6 +1,6 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; RUN: opt < %s -O2 -S -enable-memcpyopt-memoryssa=0 | FileCheck %s --check-prefixes=CHECK,NO_MSSA -; RUN: opt < %s -O2 -S -enable-memcpyopt-memoryssa=1 -verify-memoryssa | FileCheck %s --check-prefixes=CHECK,MSSA +; RUN: opt < %s -O2 -S -enable-memcpyopt-memoryssa=0 | FileCheck %s +; RUN: opt < %s -O2 -S -enable-memcpyopt-memoryssa=1 -verify-memoryssa | FileCheck %s ; performCallSlotOptzn in MemCpy should not exchange the calls to ; @llvm.lifetime.start and @llvm.memcpy. @@ -27,29 +27,17 @@ ret void } -; FIXME: Miscompile. define void @memcpy_memcpy_across_lifetime(i8* noalias %p1, i8* noalias %p2, i8* noalias %p3) { -; NO_MSSA-LABEL: @memcpy_memcpy_across_lifetime( -; NO_MSSA-NEXT: [[A:%.*]] = alloca [16 x i8], align 1 -; NO_MSSA-NEXT: [[A8:%.*]] = getelementptr inbounds [16 x i8], [16 x i8]* [[A]], i64 0, i64 0 -; NO_MSSA-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[A8]]) -; NO_MSSA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[A8]], i8* nonnull align 1 dereferenceable(16) [[P1:%.*]], i64 16, i1 false) -; NO_MSSA-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P1]], i8* nonnull align 1 dereferenceable(16) [[P2:%.*]], i64 16, i1 false) -; NO_MSSA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P2]], i8* nonnull align 1 dereferenceable(16) [[A8]], i64 16, i1 false) -; NO_MSSA-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[A8]]) -; NO_MSSA-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P3:%.*]], i8* nonnull align 1 dereferenceable(16) [[P2]], i64 16, i1 false) -; NO_MSSA-NEXT: ret void -; -; MSSA-LABEL: @memcpy_memcpy_across_lifetime( -; MSSA-NEXT: [[A:%.*]] = alloca [16 x i8], align 1 -; MSSA-NEXT: [[A8:%.*]] = getelementptr inbounds [16 x i8], [16 x i8]* [[A]], i64 0, i64 0 -; MSSA-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[A8]]) -; MSSA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[A8]], i8* nonnull align 1 dereferenceable(16) [[P1:%.*]], i64 16, i1 false) -; MSSA-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P1]], i8* nonnull align 1 dereferenceable(16) [[P2:%.*]], i64 16, i1 false) -; MSSA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P2]], i8* nonnull align 1 dereferenceable(16) [[A8]], i64 16, i1 false) -; MSSA-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[A8]]) -; MSSA-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P3:%.*]], i8* nonnull align 1 dereferenceable(16) [[A8]], i64 16, i1 false) -; MSSA-NEXT: ret void +; CHECK-LABEL: @memcpy_memcpy_across_lifetime( +; CHECK-NEXT: [[A:%.*]] = alloca [16 x i8], align 1 +; CHECK-NEXT: [[A8:%.*]] = getelementptr inbounds [16 x i8], [16 x i8]* [[A]], i64 0, i64 0 +; CHECK-NEXT: call void @llvm.lifetime.start.p0i8(i64 16, i8* nonnull [[A8]]) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[A8]], i8* nonnull align 1 dereferenceable(16) [[P1:%.*]], i64 16, i1 false) +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P1]], i8* nonnull align 1 dereferenceable(16) [[P2:%.*]], i64 16, i1 false) +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P2]], i8* nonnull align 1 dereferenceable(16) [[A8]], i64 16, i1 false) +; CHECK-NEXT: call void @llvm.lifetime.end.p0i8(i64 16, i8* nonnull [[A8]]) +; CHECK-NEXT: tail call void @llvm.memcpy.p0i8.p0i8.i64(i8* nonnull align 1 dereferenceable(16) [[P3:%.*]], i8* nonnull align 1 dereferenceable(16) [[P2]], i64 16, i1 false) +; CHECK-NEXT: ret void ; %a = alloca [16 x i8] %a8 = bitcast [16 x i8]* %a to i8*