[llvm] [memcpyopt] handle memcpy from memset for non-constant sizes (PR #143727)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 11 08:26:48 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Jameson Nash (vtjnash)
<details>
<summary>Changes</summary>
Remove some unnecessary checks in the code so it can handle more cases of optimization. Refs #<!-- -->140954 which laid some of the groundwork for this.
---
Full diff: https://github.com/llvm/llvm-project/pull/143727.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp (+19-19)
- (modified) llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll (+1-1)
``````````diff
diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
index 960001bf880c6..1c4ec6aa08b43 100644
--- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
+++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp
@@ -1440,7 +1440,7 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
int64_t MOffset = 0;
const DataLayout &DL = MemCpy->getModule()->getDataLayout();
// We can only transforms memcpy's where the dest of one is the source of the
- // other, or the memory transfer has a known offset from the memset.
+ // other, or they have a known offset.
if (MemCpy->getSource() != MemSet->getDest()) {
std::optional<int64_t> Offset =
MemCpy->getSource()->getPointerOffsetFrom(MemSet->getDest(), DL);
@@ -1451,28 +1451,28 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
if (MOffset != 0 || MemSetSize != CopySize) {
// Make sure the memcpy doesn't read any more than what the memset wrote,
- // other than undef. Don't worry about sizes larger than i64. A known memset
- // size is required.
+ // other than undef. Don't worry about sizes larger than i64.
auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
- if (!CMemSetSize)
- return false;
-
- // A known memcpy size is also required.
auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
- if (!CCopySize)
- return false;
- if (CCopySize->getZExtValue() + MOffset > CMemSetSize->getZExtValue()) {
+ if (!CMemSetSize || !CCopySize ||
+ CCopySize->getZExtValue() + MOffset > CMemSetSize->getZExtValue()) {
if (!overreadUndefContents(MSSA, MemCpy, MemSet, BAA))
return false;
- // Clip the memcpy to the bounds of the memset
- if (MOffset == 0)
- CopySize = MemSetSize;
- else
- CopySize =
- ConstantInt::get(CopySize->getType(),
- CMemSetSize->getZExtValue() <= (uint64_t)MOffset
- ? 0
- : CMemSetSize->getZExtValue() - MOffset);
+
+ if (CMemSetSize && CCopySize) {
+ // If both have constant sizes and offsets, clip the memcpy to the
+ // bounds of the memset if applicable.
+ assert(CCopySize->getZExtValue() + MOffset >
+ CMemSetSize->getZExtValue());
+ if (MOffset == 0)
+ CopySize = MemSetSize;
+ else
+ CopySize =
+ ConstantInt::get(CopySize->getType(),
+ CMemSetSize->getZExtValue() <= (uint64_t)MOffset
+ ? 0
+ : CMemSetSize->getZExtValue() - MOffset);
+ }
}
}
diff --git a/llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll b/llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll
index d5b1ab9b2f299..3dcf0b1868800 100644
--- a/llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll
+++ b/llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll
@@ -24,7 +24,7 @@ define void @negative_test(ptr %src, i8 %c, i64 %size1, i64 %size2) {
; CHECK-NEXT: [[DST1:%.*]] = alloca i8, i64 [[SIZE1:%.*]], align 1
; CHECK-NEXT: [[DST2:%.*]] = alloca i8, i64 [[SIZE2:%.*]], align 1
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[DST1]], i8 [[C:%.*]], i64 [[SIZE1]], i1 false)
-; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST2]], ptr align 8 [[DST1]], i64 [[SIZE2]], i1 false)
+; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[DST2]], i8 [[C]], i64 [[SIZE2]], i1 false)
; CHECK-NEXT: ret void
;
%dst1 = alloca i8, i64 %size1
``````````
</details>
https://github.com/llvm/llvm-project/pull/143727
More information about the llvm-commits
mailing list