diff --git a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp --- a/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp +++ b/llvm/lib/Transforms/Scalar/MemCpyOptimizer.cpp @@ -1199,12 +1199,14 @@ /// In other words, transform: /// \code /// memset(dst, c, dst_size); +/// ... /// memcpy(dst, src, src_size); /// \endcode /// into: /// \code -/// memcpy(dst, src, src_size); +/// ... /// memset(dst + src_size, c, dst_size <= src_size ? 0 : dst_size - src_size); +/// memcpy(dst, src, src_size); /// \endcode bool MemCpyOptPass::processMemSetMemCpyDependence(MemCpyInst *MemCpy, MemSetInst *MemSet) { @@ -1250,8 +1252,21 @@ if (auto *SrcSizeC = dyn_cast(SrcSize)) Alignment = commonAlignment(DestAlign, SrcSizeC->getZExtValue()); + // SrcSize must be available for the pointer/size calculations. Therefore we + // insert the new memset immediately before the MemCpy. An alternative would + // be to insert it just after the MemCpy. + // FIXME: If we want to insert the new memset above the memcpy, then we might + // wannt skip backward past any dbg instructions that are immediate + // predecessors to the memcpy. Any such dbg instructions were between the + // memset and the memcpy originally, so sinking the memset past them seems a + // bit reckless. IRBuilder<> Builder(MemCpy); + // FIXME: For debugability etc. it might be better to use the debug location + // of the old memset for the code emitted here rather than using the debug + // location from the MemCpy as we do right now. + // Builder.SetCurrentDebugLocation(MemSet->getDebugLoc()); + // If the sizes have different types, zext the smaller one. if (DestSize->getType() != SrcSize->getType()) { if (DestSize->getType()->getIntegerBitWidth() > @@ -1275,9 +1290,8 @@ assert(isa(MSSAU->getMemorySSA()->getMemoryAccess(MemCpy)) && "MemCpy must be a MemoryDef"); - // The new memset is inserted after the memcpy, but it is known that its - // defining access is the memset about to be removed which immediately - // precedes the memcpy. + // The new memset is inserted before the memcpy, and it is known that the + // memcpy:s defining access is the memset about to be removed. auto *LastDef = cast(MSSAU->getMemorySSA()->getMemoryAccess(MemCpy)); auto *NewAccess = MSSAU->createMemoryAccessBefore(