@@ -1364,8 +1364,9 @@ bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy,
13641364 return true ;
13651365}
13661366
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.
13691370static bool hasUndefContents (MemorySSA *MSSA, BatchAAResults &AA, Value *V,
13701371 MemoryDef *Def, Value *Size) {
13711372 if (MSSA->isLiveOnEntryDef (Def))
@@ -1400,6 +1401,24 @@ static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
14001401 return false ;
14011402}
14021403
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+
14031422// / Transform memcpy to memset when its source was just memset.
14041423// / In other words, turn:
14051424// / \code
@@ -1415,19 +1434,25 @@ static bool hasUndefContents(MemorySSA *MSSA, BatchAAResults &AA, Value *V,
14151434bool MemCpyOptPass::performMemCpyToMemSetOptzn (MemCpyInst *MemCpy,
14161435 MemSetInst *MemSet,
14171436 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-
14231437 Value *MemSetSize = MemSet->getLength ();
14241438 Value *CopySize = MemCpy->getLength ();
14251439
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+ }
14291451
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.
14311456 auto *CMemSetSize = dyn_cast<ConstantInt>(MemSetSize);
14321457 if (!CMemSetSize)
14331458 return false ;
@@ -1436,23 +1461,18 @@ bool MemCpyOptPass::performMemCpyToMemSetOptzn(MemCpyInst *MemCpy,
14361461 auto *CCopySize = dyn_cast<ConstantInt>(CopySize);
14371462 if (!CCopySize)
14381463 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))
14541466 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);
14561476 }
14571477 }
14581478
0 commit comments