@@ -68,6 +68,7 @@ static cl::opt<bool> EnableMemCpyOptWithoutLibcalls(
6868 cl::desc (" Enable memcpyopt even when libcalls are disabled" ));
6969
7070STATISTIC (NumMemCpyInstr, " Number of memcpy instructions deleted" );
71+ STATISTIC (NumMemMoveInstr, " Number of memmove instructions deleted" );
7172STATISTIC (NumMemSetInfer, " Number of memsets inferred" );
7273STATISTIC (NumMoveToCpy, " Number of memmoves converted to memcpy" );
7374STATISTIC (NumCpyToSet, " Number of memcpys converted to memset" );
@@ -1841,12 +1842,87 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
18411842 return false ;
18421843}
18431844
1845+ // / Memmove calls with overlapping src/dest buffers that come after a memset may
1846+ // / be removed.
1847+ bool MemCpyOptPass::isMemMoveMemSetDependency (MemMoveInst *M) {
1848+ const auto &DL = M->getDataLayout ();
1849+ MemoryUseOrDef *MemMoveAccess = MSSA->getMemoryAccess (M);
1850+ if (!MemMoveAccess)
1851+ return false ;
1852+
1853+ // The memmove is of form memmove(x, x + A, B).
1854+ MemoryLocation SourceLoc = MemoryLocation::getForSource (M);
1855+ auto *MemMoveSourceOp = M->getSource ();
1856+ auto *Source = dyn_cast<GetElementPtrInst>(MemMoveSourceOp);
1857+ bool MemMoveHasGEPOperator = false ;
1858+ if (!Source) {
1859+ if (auto *CE = dyn_cast<ConstantExpr>(MemMoveSourceOp))
1860+ if (isa<GEPOperator>(CE)) {
1861+ Source = cast<GetElementPtrInst>(CE->getAsInstruction ());
1862+ MemMoveHasGEPOperator = true ;
1863+ }
1864+ if (!Source)
1865+ return false ;
1866+ }
1867+
1868+ APInt Offset (DL.getIndexTypeSizeInBits (Source->getType ()), 0 );
1869+ LocationSize MemMoveLocSize = SourceLoc.Size ;
1870+ if (Source->getPointerOperand () != M->getDest () ||
1871+ !MemMoveLocSize.hasValue () || Offset.isNegative () ||
1872+ !Source->accumulateConstantOffset (DL, Offset)) {
1873+ if (MemMoveHasGEPOperator)
1874+ Source->dropAllReferences ();
1875+ return false ;
1876+ }
1877+
1878+ if (MemMoveHasGEPOperator)
1879+ Source->dropAllReferences ();
1880+
1881+ const uint64_t MemMoveSize = MemMoveLocSize.getValue ();
1882+ LocationSize TotalSize =
1883+ LocationSize::precise (Offset.getZExtValue () + MemMoveSize);
1884+ MemoryLocation CombinedSourceLoc (MemMoveSourceOp, TotalSize);
1885+ MemoryLocation CombinedDestLoc (M->getDest (), TotalSize);
1886+
1887+ // The first dominating clobbering MemoryAccess for the combined location
1888+ // needs to be a memset.
1889+ BatchAAResults BAA (*AA);
1890+ MemSetInst *MS = nullptr ;
1891+ MemoryAccess *FirstDef = MemMoveAccess->getDefiningAccess ();
1892+ MemoryAccess *DestClobber = MSSA->getWalker ()->getClobberingMemoryAccess (
1893+ FirstDef, CombinedDestLoc, BAA);
1894+ if (auto *Def = dyn_cast<MemoryDef>(DestClobber))
1895+ MS = dyn_cast_or_null<MemSetInst>(Def->getMemoryInst ());
1896+ if (!MS)
1897+ return false ;
1898+
1899+ // Memset length must be sufficiently large.
1900+ if (cast<ConstantInt>(MS->getLength ())->getZExtValue () < MemMoveSize)
1901+ return false ;
1902+
1903+ // The destination buffer must have been memset'd.
1904+ if (!BAA.isMustAlias (MS->getDest (), M->getDest ()))
1905+ return false ;
1906+
1907+ return true ;
1908+ }
1909+
18441910// / Transforms memmove calls to memcpy calls when the src/dst are guaranteed
18451911// / not to alias.
1846- bool MemCpyOptPass::processMemMove (MemMoveInst *M) {
1912+ bool MemCpyOptPass::processMemMove (MemMoveInst *M, BasicBlock::iterator &BBI ) {
18471913 // See if the source could be modified by this memmove potentially.
1848- if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M))))
1914+ if (isModSet (AA->getModRefInfo (M, MemoryLocation::getForSource (M)))) {
1915+ // On the off-chance the memmove clobbers src with previously memset'd
1916+ // bytes, the memmove may be redundant.
1917+ if (!M->isVolatile () && isMemMoveMemSetDependency (M)) {
1918+ LLVM_DEBUG (dbgs () << " Removed redundant memmove.\n " );
1919+ ++BBI;
1920+ eraseInstruction (M);
1921+ ++NumMemMoveInstr;
1922+ return true ;
1923+ }
18491924 return false ;
1925+ }
18501926
18511927 LLVM_DEBUG (dbgs () << " MemCpyOptPass: Optimizing memmove -> memcpy: " << *M
18521928 << " \n " );
@@ -2064,7 +2140,7 @@ bool MemCpyOptPass::iterateOnFunction(Function &F) {
20642140 else if (auto *M = dyn_cast<MemCpyInst>(I))
20652141 RepeatInstruction = processMemCpy (M, BI);
20662142 else if (auto *M = dyn_cast<MemMoveInst>(I))
2067- RepeatInstruction = processMemMove (M);
2143+ RepeatInstruction = processMemMove (M, BI );
20682144 else if (auto *CB = dyn_cast<CallBase>(I)) {
20692145 for (unsigned i = 0 , e = CB->arg_size (); i != e; ++i) {
20702146 if (CB->isByValArgument (i))
0 commit comments