[llvm] [MemCpyOpt] Drop dead `memmove` calls on `memset`'d source data (PR #101930)

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 28 08:28:53 PST 2024


================
@@ -1843,12 +1844,68 @@ bool MemCpyOptPass::processMemCpy(MemCpyInst *M, BasicBlock::iterator &BBI) {
   return false;
 }
 
+/// Memmove calls with overlapping src/dest buffers that come after a memset may
+/// be removed.
+bool MemCpyOptPass::isMemMoveMemSetDependency(MemMoveInst *M) {
+  const auto &DL = M->getDataLayout();
+  MemoryUseOrDef *MemMoveAccess = MSSA->getMemoryAccess(M);
+  if (!MemMoveAccess)
+    return false;
+
+  // The memmove is of form memmove(x, x + A, B).
+  MemoryLocation SourceLoc = MemoryLocation::getForSource(M);
+  auto *Source = dyn_cast<GetElementPtrInst>(M->getSource());
+  if (!Source)
+    return false;
+  APInt Offset(DL.getIndexTypeSizeInBits(Source->getType()), 0);
+  auto MemMoveSize = SourceLoc.Size;
+  if (!Source->accumulateConstantOffset(DL, Offset) || Offset.isNegative() ||
+      Source->getPointerOperand() != M->getDest() || !MemMoveSize.hasValue())
+    return false;
+
+  LocationSize TotalSize =
+      LocationSize::precise(Offset.getZExtValue() + MemMoveSize.getValue());
+  MemoryLocation CombinedSourceLoc(M->getSource(), TotalSize);
+  MemoryLocation CombinedDestLoc(M->getDest(), TotalSize);
+
+  // The first dominating clobbering MemoryAccess for the combined location
+  // needs to be a memset.
+  BatchAAResults BAA(*AA);
+  MemSetInst *MS = nullptr;
+  MemoryAccess *FirstDef = MemMoveAccess->getDefiningAccess();
+  MemoryAccess *DestClobber = MSSA->getWalker()->getClobberingMemoryAccess(
+      FirstDef, CombinedDestLoc, BAA);
+  if (auto *Def = dyn_cast<MemoryDef>(DestClobber))
+    MS = dyn_cast_or_null<MemSetInst>(Def->getMemoryInst());
+  if (!MS)
+    return false;
+
+  // The destination buffer must have been memset'd.
+  if (!BAA.isMustAlias(MS->getDest(), M->getDest()))
+    return false;
+
+  if (!isModOrRefSet(BAA.getModRefInfo(MS, CombinedSourceLoc)) ||
+      !isModOrRefSet(BAA.getModRefInfo(MS, CombinedDestLoc)))
+    return false;
----------------
nikic wrote:

I don't think these getModRefInfo() queries are needed? This is implied by the isMustAlias call already.

A check I am missing though is that the memset size is sufficiently large. I think currently your transform would trigger on a partial memset?

https://github.com/llvm/llvm-project/pull/101930


More information about the llvm-commits mailing list