Skip to content

Commit 61d16aa

Browse files
committed
[memcpyopt] handle memcpy from memset for non-constant sizes
1 parent 0759e08 commit 61d16aa

File tree

2 files changed

+20
-20
lines changed

2 files changed

+20
-20
lines changed

llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1443,7 +1443,7 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
14431443
int64_t MOffset = 0;
14441444
const DataLayout &DL = MemCpy->getModule()->getDataLayout();
14451445
// We can only transforms memcpy's where the dest of one is the source of the
1446-
// other, or the memory transfer has a known offset from the memset.
1446+
// other, or they have a known offset.
14471447
if (MemCpy->getSource() != MemSet->getDest()) {
14481448
std::optional<int64_t> Offset =
14491449
MemCpy->getSource()->getPointerOffsetFrom(MemSet->getDest(), DL);
@@ -1454,28 +1454,28 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
14541454

14551455
if (MOffset != 0 || MemSetSize != CopySize) {
14561456
// Make sure the memcpy doesn't read any more than what the memset wrote,
1457-
// other than undef. Don't worry about sizes larger than i64. A known memset
1458-
// size is required.
1457+
// other than undef. Don't worry about sizes larger than i64.
14591458
auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
1460-
if (!CMemSetSize)
1461-
return false;
1462-
1463-
// A known memcpy size is also required.
14641459
auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
1465-
if (!CCopySize)
1466-
return false;
1467-
if (CCopySize->getZExtValue() + MOffset > CMemSetSize->getZExtValue()) {
1460+
if (!CMemSetSize || !CCopySize ||
1461+
CCopySize->getZExtValue() + MOffset > CMemSetSize->getZExtValue()) {
14681462
if (!overreadUndefContents(MSSA, MemCpy, MemSet, BAA))
14691463
return false;
1470-
// Clip the memcpy to the bounds of the memset
1471-
if (MOffset == 0)
1472-
CopySize = MemSetSize;
1473-
else
1474-
CopySize =
1475-
ConstantInt::get(CopySize->getType(),
1476-
CMemSetSize->getZExtValue() <= (uint64_t)MOffset
1477-
? 0
1478-
: CMemSetSize->getZExtValue() - MOffset);
1464+
1465+
if (CMemSetSize && CCopySize) {
1466+
// If both have constant sizes and offsets, clip the memcpy to the
1467+
// bounds of the memset if applicable.
1468+
assert(CCopySize->getZExtValue() + MOffset >
1469+
CMemSetSize->getZExtValue());
1470+
if (MOffset == 0)
1471+
CopySize = MemSetSize;
1472+
else
1473+
CopySize =
1474+
ConstantInt::get(CopySize->getType(),
1475+
CMemSetSize->getZExtValue() <= (uint64_t)MOffset
1476+
? 0
1477+
: CMemSetSize->getZExtValue() - MOffset);
1478+
}
14791479
}
14801480
}
14811481

llvm/test/Transforms/MemCpyOpt/variable-sized-memset-memcpy.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ define void @negative_test(ptr %src, i8 %c, i64 %size1, i64 %size2) {
2424
; CHECK-NEXT: [[DST1:%.*]] = alloca i8, i64 [[SIZE1:%.*]], align 1
2525
; CHECK-NEXT: [[DST2:%.*]] = alloca i8, i64 [[SIZE2:%.*]], align 1
2626
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[DST1]], i8 [[C:%.*]], i64 [[SIZE1]], i1 false)
27-
; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr align 8 [[DST2]], ptr align 8 [[DST1]], i64 [[SIZE2]], i1 false)
27+
; CHECK-NEXT: call void @llvm.memset.p0.i64(ptr align 8 [[DST2]], i8 [[C]], i64 [[SIZE2]], i1 false)
2828
; CHECK-NEXT: ret void
2929
;
3030
%dst1 = alloca i8, i64 %size1

0 commit comments

Comments
 (0)