Index: llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp =================================================================== --- llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1423,7 +1423,8 @@ } MemoryUseOrDef *MA = MSSA->getMemoryAccess(M); - MemoryAccess *AnyClobber = MSSA->getWalker()->getClobberingMemoryAccess(MA); + // FIXME: Not using getClobberingMemoryAccess() here due to PR54682. + MemoryAccess *AnyClobber = MA->getDefiningAccess(); MemoryLocation DestLoc = MemoryLocation::getForDest(M); const MemoryAccess *DestClobber = MSSA->getWalker()->getClobberingMemoryAccess(AnyClobber, DestLoc); Index: llvm/test/Transforms/MemCpyOpt/pr54682.ll =================================================================== --- llvm/test/Transforms/MemCpyOpt/pr54682.ll +++ llvm/test/Transforms/MemCpyOpt/pr54682.ll @@ -1,7 +1,8 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -memcpyopt < %s | FileCheck %s -; FIXME: This currently gets miscompiled. +; The memcpy here is *not* dead, because it reads memory written in a previous +; loop iteration. define void @test(i1 %c, i8* nocapture noundef readonly %path, i8* noundef writeonly %name) { ; CHECK-LABEL: @test( @@ -17,6 +18,7 @@ ; CHECK: exit: ; CHECK-NEXT: [[TMP_IV_1:%.*]] = getelementptr inbounds i8, i8* [[TMP_IV]], i64 1 ; CHECK-NEXT: [[LEN:%.*]] = sub nsw i64 259, [[IV]] +; CHECK-NEXT: call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 [[NAME:%.*]], i8* nonnull align 1 [[TMP_IV_1]], i64 [[LEN]], i1 false) ; CHECK-NEXT: ret void ; entry: