[llvm] 09d1b94 - [MemCpyOpt] Fix incorrect size check in memmove of memset opt (#206451)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 05:37:16 PDT 2026


Author: Nikita Popov
Date: 2026-06-29T14:37:11+02:00
New Revision: 09d1b945b52e9cdb318842a051bab8fbc3d83d9f

URL: https://github.com/llvm/llvm-project/commit/09d1b945b52e9cdb318842a051bab8fbc3d83d9f
DIFF: https://github.com/llvm/llvm-project/commit/09d1b945b52e9cdb318842a051bab8fbc3d83d9f.diff

LOG: [MemCpyOpt] Fix incorrect size check in memmove of memset opt (#206451)

We were only checking that the memset is at least as large as the
memmove size, but not accounting for the fact that the memmove occurs at
an offset.

Added: 
    

Modified: 
    llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
    llvm/test/Transforms/MemCpyOpt/memset-memmove-redundant-memmove.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 3f6bb6f408797..3fc84f2fc8c13 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1963,7 +1963,8 @@ bool MemCpyOptPass::isMemMoveMemSetDependency(MemMoveInst *M) {
 
   // Memset length must be sufficiently large.
   auto *MemSetLength = dyn_cast<ConstantInt>(MS->getLength());
-  if (!MemSetLength || MemSetLength->getZExtValue() < MemMoveSize)
+  if (!MemSetLength ||
+      MemSetLength->getZExtValue() < Offset.getZExtValue() + MemMoveSize)
     return false;
 
   // The destination buffer must have been memset'd.

diff  --git a/llvm/test/Transforms/MemCpyOpt/memset-memmove-redundant-memmove.ll b/llvm/test/Transforms/MemCpyOpt/memset-memmove-redundant-memmove.ll
index c7593e2941518..ab4d501c01e06 100644
--- a/llvm/test/Transforms/MemCpyOpt/memset-memmove-redundant-memmove.ll
+++ b/llvm/test/Transforms/MemCpyOpt/memset-memmove-redundant-memmove.ll
@@ -175,6 +175,20 @@ define i32 @memset_memmove_dest_buffers_not_alias() {
   ret i32 %val
 }
 
+; memset covers size of memmove but not the source offset.
+define void @memset_shorter_than_offset_plus_size(ptr %array) {
+; CHECK-LABEL: @memset_shorter_than_offset_plus_size(
+; CHECK-NEXT:    call void @llvm.memset.p0.i64(ptr align 16 [[ARRAY:%.*]], i8 0, i64 8, i1 false)
+; CHECK-NEXT:    [[ARRAY_IDX:%.*]] = getelementptr inbounds i8, ptr [[ARRAY]], i64 4
+; CHECK-NEXT:    call void @llvm.memmove.p0.p0.i64(ptr align 16 [[ARRAY]], ptr align 4 [[ARRAY_IDX]], i64 8, i1 false)
+; CHECK-NEXT:    ret void
+;
+  call void @llvm.memset.p0.i64(ptr align 16 %array, i8 0, i64 8, i1 false)
+  %array.idx = getelementptr inbounds i8, ptr %array, i64 4
+  call void @llvm.memmove.p0.p0.i64(ptr align 16 %array, ptr align 4 %array.idx, i64 8, i1 false)
+  ret void
+}
+
 declare void @opaque(ptr)
 declare void @llvm.memset.p0.i64(ptr nocapture, i8, i64, i1)
 declare void @llvm.memmove.p0.p0.i64(ptr nocapture, ptr nocapture, i64, i1)


        


More information about the llvm-commits mailing list