@@ -1364,8 +1364,9 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
1364
1364
return true ;
1365
1365
}
1366
1366
1367
- // / Determine whether the instruction has undefined content for the given Size,
1368
- // / either because it was freshly alloca'd or started its lifetime.
1367
+ // / Determine whether the pointer V had only undefined content (due to Def) up
1368
+ // / to the given Size, either because it was freshly alloca'd or started its
1369
+ // / lifetime.
1369
1370
static bool hasUndefContents (MemorySSA *MSSA, BatchAAResults &AA, Value *V,
1370
1371
MemoryDef *Def, Value *Size) {
1371
1372
if (MSSA->isLiveOnEntryDef (Def))
@@ -1400,6 +1401,24 @@ static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
1400
1401
return false ;
1401
1402
}
1402
1403
1404
+ // If the memcpy is larger than the previous, but the memory was undef prior to
1405
+ // that, we can just ignore the tail. Technically we're only interested in the
1406
+ // bytes from 0..MemSrcOffset and MemSrcLength+MemSrcOffset..CopySize here, but
1407
+ // as we can't easily represent this location (hasUndefContents uses mustAlias
1408
+ // which cannot deal with offsets), we use the full 0..CopySize range.
1409
+ static bool overreadUndefContents (MemorySSA *MSSA, MemCpyInst *MemCpy,
1410
+ MemIntrinsic *MemSrc, BatchAAResults &BAA) {
1411
+ Value *CopySize = MemCpy->getLength ();
1412
+ MemoryLocation MemCpyLoc = MemoryLocation::getForSource (MemCpy);
1413
+ MemoryUseOrDef *MemSrcAccess = MSSA->getMemoryAccess (MemSrc);
1414
+ MemoryAccess *Clobber = MSSA->getWalker ()->getClobberingMemoryAccess (
1415
+ MemSrcAccess->getDefiningAccess (), MemCpyLoc, BAA);
1416
+ if (auto *MD = dyn_cast<MemoryDef>(Clobber))
1417
+ if (hasUndefContents (MSSA, BAA, MemCpy->getSource (), MD, CopySize))
1418
+ return true ;
1419
+ return false ;
1420
+ }
1421
+
1403
1422
// / Transform memcpy to memset when its source was just memset.
1404
1423
// / In other words, turn:
1405
1424
// / \code
@@ -1415,19 +1434,25 @@ static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
1415
1434
bool MemCpyOptPass::performMemCpyToMemSetOptzn (MemCpyInst *MemCpy,
1416
1435
MemSetInst *MemSet,
1417
1436
BatchAAResults &BAA) {
1418
- // Make sure that memcpy(..., memset(...), ...), that is we are memsetting and
1419
- // memcpying from the same address. Otherwise it is hard to reason about.
1420
- if (!BAA.isMustAlias (MemSet->getRawDest (), MemCpy->getRawSource ()))
1421
- return false ;
1422
-
1423
1437
Value *MemSetSize = MemSet->getLength ();
1424
1438
Value *CopySize = MemCpy->getLength ();
1425
1439
1426
- if (MemSetSize != CopySize) {
1427
- // Make sure the memcpy doesn't read any more than what the memset wrote.
1428
- // Don't worry about sizes larger than i64.
1440
+ int64_t MOffset = 0 ;
1441
+ const DataLayout &DL = MemCpy->getModule ()->getDataLayout ();
1442
+ // We can only transforms memcpy's where the dest of one is the source of the
1443
+ // other, or the memory transfer has a known offset from the memset.
1444
+ if (MemCpy->getSource () != MemSet->getDest ()) {
1445
+ std::optional<int64_t > Offset =
1446
+ MemCpy->getSource ()->getPointerOffsetFrom (MemSet->getDest (), DL);
1447
+ if (!Offset || *Offset < 0 )
1448
+ return false ;
1449
+ MOffset = *Offset;
1450
+ }
1429
1451
1430
- // A known memset size is required.
1452
+ if (MOffset != 0 || MemSetSize != CopySize) {
1453
+ // Make sure the memcpy doesn't read any more than what the memset wrote,
1454
+ // other than undef. Don't worry about sizes larger than i64. A known memset
1455
+ // size is required.
1431
1456
auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
1432
1457
if (!CMemSetSize)
1433
1458
return false ;
@@ -1436,23 +1461,18 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
1436
1461
auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
1437
1462
if (!CCopySize)
1438
1463
return false ;
1439
- if (CCopySize->getZExtValue () > CMemSetSize->getZExtValue ()) {
1440
- // If the memcpy is larger than the memset, but the memory was undef prior
1441
- // to the memset, we can just ignore the tail. Technically we're only
1442
- // interested in the bytes from MemSetSize..CopySize here, but as we can't
1443
- // easily represent this location, we use the full 0..CopySize range.
1444
- MemoryLocation MemCpyLoc = MemoryLocation::getForSource (MemCpy);
1445
- bool CanReduceSize = false ;
1446
- MemoryUseOrDef *MemSetAccess = MSSA->getMemoryAccess (MemSet);
1447
- MemoryAccess *Clobber = MSSA->getWalker ()->getClobberingMemoryAccess (
1448
- MemSetAccess->getDefiningAccess (), MemCpyLoc, BAA);
1449
- if (auto *MD = dyn_cast<MemoryDef>(Clobber))
1450
- if (hasUndefContents (MSSA, BAA, MemCpy->getSource (), MD, CopySize))
1451
- CanReduceSize = true ;
1452
-
1453
- if (!CanReduceSize)
1464
+ if (CCopySize->getZExtValue () + MOffset > CMemSetSize->getZExtValue ()) {
1465
+ if (!overreadUndefContents (MSSA, MemCpy, MemSet, BAA))
1454
1466
return false ;
1455
- CopySize = MemSetSize;
1467
+ // Clip the memcpy to the bounds of the memset
1468
+ if (MOffset == 0 )
1469
+ CopySize = MemSetSize;
1470
+ else
1471
+ CopySize =
1472
+ ConstantInt::get (CopySize->getType (),
1473
+ CMemSetSize->getZExtValue () <= (uint64_t )MOffset
1474
+ ? 0
1475
+ : CMemSetSize->getZExtValue () - MOffset);
1456
1476
}
1457
1477
}
1458
1478
0 commit comments