@@ -69,6 +69,7 @@ static cl::opt<bool> EnableMemCpyOptWithoutLibcalls(
6969 cl::desc (" Enable memcpyopt even when libcalls are disabled" ));
7070
7171STATISTIC (NumMemCpyInstr, " Number of memcpy instructions deleted" );
72+ STATISTIC (NumMemMoveInstr, " Number of memmove instructions deleted" );
7273STATISTIC (NumMemSetInfer, " Number of memsets inferred" );
7374STATISTIC (NumMoveToCpy, " Number of memmoves converted to memcpy" );
7475STATISTIC (NumCpyToSet, " Number of memcpys converted to memset" );
@@ -1843,12 +1844,77 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
18431844 return false ;
18441845}
18451846
1847+ // / Memmove calls with overlapping src/dest buffers that come after a memset may
1848+ // / be removed.
1849+ bool MemCpyOptPass::isMemMoveMemSetDependency (MemMoveInst *M) {
1850+ const auto &DL = M->getDataLayout ();
1851+ MemSetInst *MS = nullptr ;
1852+ MemoryUseOrDef *MemMoveAccess = MSSA->getMemoryAccess (M);
1853+ if (!MemMoveAccess)
1854+ return false ;
1855+
1856+ BatchAAResults BAA (*AA);
1857+ MemoryAccess *FirstDef = MemMoveAccess->getDefiningAccess ();
1858+ MemoryLocation SourceLoc = MemoryLocation::getForSource (M);
1859+ MemoryLocation DestLoc = MemoryLocation::getForDest (M);
1860+
1861+ // The first dominating clobbering MemoryAccess for the source location
1862+ // needs to be the memset.
1863+ MemoryAccess *SourceClobber =
1864+ MSSA->getWalker ()->getClobberingMemoryAccess (FirstDef, SourceLoc, BAA);
1865+ if (auto *Def = dyn_cast<MemoryDef>(SourceClobber))
1866+ MS = dyn_cast_or_null<MemSetInst>(Def->getMemoryInst ());
1867+ if (!MS)
1868+ return false ;
1869+
1870+ // The destination buffer must have been memset'd.
1871+ if (!BAA.isMustAlias (MS->getDest (), M->getDest ()))
1872+ return false ;
1873+
1874+ // The memmove is of form memmove(x, x + A, B).
1875+ auto *Source = dyn_cast<GetElementPtrInst>(M->getSource ());
1876+ if (!Source)
1877+ return false ;
1878+ APInt Offset (DL.getIndexTypeSizeInBits (Source->getType ()), 0 );
1879+ auto MemMoveSize = MemoryLocation::getForSource (M).Size ;
1880+ if (!Source->accumulateConstantOffset (DL, Offset) || Offset.isNegative () ||
1881+ Source->getPointerOperand () != M->getDest () || !MemMoveSize.hasValue ())
1882+ return false ;
1883+
1884+ LocationSize TotalSize =
1885+ LocationSize::precise (Offset.getZExtValue () + MemMoveSize.getValue ());
1886+ MemoryLocation CombinedSourceLoc (M->getSource (), TotalSize);
1887+ MemoryLocation CombinedDestLoc (M->getDest (), TotalSize);
1888+ if (!isModOrRefSet (BAA.getModRefInfo (MS, CombinedSourceLoc)) ||
1889+ !isModOrRefSet (BAA.getModRefInfo (MS, CombinedDestLoc)))
1890+ return false ;
1891+
1892+ // The first dominating clobbering MemoryAccess for the destination location
1893+ // needs to be the memset as well.
1894+ MemoryAccess *DestClobber =
1895+ MSSA->getWalker ()->getClobberingMemoryAccess (FirstDef, DestLoc, BAA);
1896+ auto *Def = dyn_cast<MemoryDef>(DestClobber);
1897+ if (Def->getMemoryInst () != MS)
1898+ return false ;
1899+ return true ;
1900+ }
1901+
18461902// / Transforms memmove calls to memcpy calls when the src/dst are guaranteed
18471903// / not to alias.
1848- bool MemCpyOptPass::processMemMove (MemMoveInst *M) {
1904+ bool MemCpyOptPass::processMemMove (MemMoveInst *M, BasicBlock::iterator &BBI ) {
18491905 // See if the source could be modified by this memmove potentially.
1850- if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M))))
1906+ if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M)))) {
1907+ // On the off-chance the memmove clobbers src with previously memset'd
1908+ // bytes, the memmove may be redundant.
1909+ if (!M->isVolatile () && isMemMoveMemSetDependency (M)) {
1910+ LLVM_DEBUG (dbgs () << " Removed redundant memmove.\n " );
1911+ ++BBI;
1912+ eraseInstruction (M);
1913+ ++NumMemMoveInstr;
1914+ return true ;
1915+ }
18511916 return false ;
1917+ }
18521918
18531919 LLVM_DEBUG (dbgs () << " MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
18541920 << " \n " );
@@ -2066,7 +2132,7 @@ bool MemCpyOptPass::iterateOnFunction(Function &F) {
20662132 else if (auto *M = dyn_cast<MemCpyInst>(I))
20672133 RepeatInstruction = processMemCpy (M, BI);
20682134 else if (auto *M = dyn_cast<MemMoveInst>(I))
2069- RepeatInstruction = processMemMove (M);
2135+ RepeatInstruction = processMemMove (M, BI );
20702136 else if (auto *CB = dyn_cast<CallBase>(I)) {
20712137 for (unsigned i = 0 , e = CB->arg_size (); i != e; ++i) {
20722138 if (CB->isByValArgument (i))
0 commit comments