@@ -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" );
@@ -1853,12 +1854,54 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
18531854 return false ;
18541855}
18551856
1857+ // / Memmove calls with overlapping src/dest buffers that come after a memset may
1858+ // / be removed.
1859+ bool MemCpyOptPass::isMemMoveMemSetDependency (MemMoveInst *M) {
1860+ MemoryUseOrDef *MemMoveAccess = MSSA->getMemoryAccess (M);
1861+ if (!MemMoveAccess)
1862+ return false ;
1863+
1864+ BatchAAResults BAA (*AA);
1865+ MemoryAccess *FirstDef = MemMoveAccess->getDefiningAccess ();
1866+ MemoryLocation SourceLoc = MemoryLocation::getForSource (M);
1867+ MemoryAccess *SourceClobber =
1868+ MSSA->getWalker ()->getClobberingMemoryAccess (FirstDef, SourceLoc, BAA);
1869+
1870+ MemSetInst *MS = nullptr ;
1871+ if (auto *Def = dyn_cast<MemoryDef>(SourceClobber))
1872+ MS = dyn_cast_or_null<MemSetInst>(Def->getMemoryInst ());
1873+
1874+ // Limit the memset to be within the same basic block.
1875+ if (!MS || MS->getParent () != M->getParent ())
1876+ return false ;
1877+
1878+ // The destination buffer must have been memset'd.
1879+ if (!BAA.isMustAlias (MS->getDest (), M->getDest ()))
1880+ return false ;
1881+
1882+ // No clobbering writes in between.
1883+ if (writtenBetween (MSSA, BAA, SourceLoc, MSSA->getMemoryAccess (MS),
1884+ MemMoveAccess))
1885+ return false ;
1886+ return true ;
1887+ }
1888+
18561889// / Transforms memmove calls to memcpy calls when the src/dst are guaranteed
18571890// / not to alias.
1858- bool MemCpyOptPass::processMemMove (MemMoveInst *M) {
1891+ bool MemCpyOptPass::processMemMove (MemMoveInst *M, BasicBlock::iterator &BBI ) {
18591892 // See if the source could be modified by this memmove potentially.
1860- if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M))))
1893+ if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M)))) {
1894+ // On the off-chance the memmove clobbers src with previously memset'd
1895+ // bytes, the memmove may be redundant.
1896+ if (!M->isVolatile () && isMemMoveMemSetDependency (M)) {
1897+ LLVM_DEBUG (dbgs () << " Removed redundant memmove.\n " );
1898+ ++BBI;
1899+ eraseInstruction (M);
1900+ ++NumMemMoveInstr;
1901+ return true ;
1902+ }
18611903 return false ;
1904+ }
18621905
18631906 LLVM_DEBUG (dbgs () << " MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
18641907 << " \n " );
@@ -2067,7 +2110,7 @@ bool MemCpyOptPass::iterateOnFunction(Function &F) {
20672110 else if (auto *M = dyn_cast<MemCpyInst>(I))
20682111 RepeatInstruction = processMemCpy (M, BI);
20692112 else if (auto *M = dyn_cast<MemMoveInst>(I))
2070- RepeatInstruction = processMemMove (M);
2113+ RepeatInstruction = processMemMove (M, BI );
20712114 else if (auto *CB = dyn_cast<CallBase>(I)) {
20722115 for (unsigned i = 0 , e = CB->arg_size (); i != e; ++i) {
20732116 if (CB->isByValArgument (i))
0 commit comments