@@ -107,6 +107,9 @@ struct MemsetRange {
107107
108108} // end anonymous namespace
109109
110+ static bool overreadUndefContents (MemorySSA *MSSA, MemCpyInst *MemCpy,
111+ MemIntrinsic *MemSrc, BatchAAResults &BAA);
112+
110113bool MemsetRange::isProfitableToUseMemset (const DataLayout &DL) const {
111114 // If we found more than 4 stores to merge or 16 bytes, use memset.
112115 if (TheStores.size () >= 4 || End - Start >= 16 )
@@ -1129,14 +1132,29 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
11291132 MForwardOffset = *Offset;
11301133 }
11311134
1132- // The length of the memcpy's must be the same, or the preceding one
1133- // must be larger than the following one.
1134- if (MForwardOffset != 0 || MDep->getLength () != M->getLength ()) {
1135+ Value *CopyLength = M->getLength ();
1136+
1137+ // The length of the memcpy's must be the same, or the preceding one must be
1138+ // larger than the following one, or the contents of the overread must be
1139+ // undefined bytes of a defined size.
1140+ if (MForwardOffset != 0 || MDep->getLength () != CopyLength) {
11351141 auto *MDepLen = dyn_cast<ConstantInt>(MDep->getLength ());
1136- auto *MLen = dyn_cast<ConstantInt>(M->getLength ());
1137- if (!MDepLen || !MLen ||
1138- MDepLen->getZExtValue () < MLen->getZExtValue () + MForwardOffset)
1142+ auto *MLen = dyn_cast<ConstantInt>(CopyLength);
1143+ // This could be converted to a runtime test (%CopyLength =
1144+ // min(max(0, MDepLen - MForwardOffset), MLen)), but it is
1145+ // unclear if that is useful
1146+ if (!MDepLen || !MLen)
11391147 return false ;
1148+ if (MDepLen->getZExtValue () < MLen->getZExtValue () + MForwardOffset) {
1149+ if (!overreadUndefContents (MSSA, M, MDep, BAA))
1150+ return false ;
1151+ if (MDepLen->getZExtValue () <= (uint64_t )MForwardOffset)
1152+ return false ; // Should not reach here (there is obviously no aliasing
1153+ // with MDep), so just bail in case it had incomplete info
1154+ // somehow
1155+ CopyLength = ConstantInt::get (CopyLength->getType (),
1156+ MDepLen->getZExtValue () - MForwardOffset);
1157+ }
11401158 }
11411159
11421160 IRBuilder<> Builder (M);
@@ -1152,9 +1170,13 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
11521170 eraseInstruction (NewCopySource);
11531171 });
11541172 MaybeAlign CopySourceAlign = MDep->getSourceAlign ();
1155- // We just need to calculate the actual size of the copy.
1156- auto MCopyLoc = MemoryLocation::getForSource (MDep).getWithNewSize (
1157- MemoryLocation::getForSource (M).Size );
1173+ auto MCopyLoc = MemoryLocation::getForSource (MDep);
1174+ // Truncate the size of the MDep access to just the bytes read
1175+ if (MDep->getLength () != CopyLength) {
1176+ auto *ConstLength = cast<ConstantInt>(CopyLength);
1177+ MCopyLoc = MCopyLoc.getWithNewSize (
1178+ LocationSize::precise (ConstLength->getZExtValue ()));
1179+ }
11581180
11591181 // When the forwarding offset is greater than 0, we transform
11601182 // memcpy(d1 <- s1)
@@ -1223,20 +1245,18 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
12231245 // example we could be moving from movaps -> movq on x86.
12241246 Instruction *NewM;
12251247 if (UseMemMove)
1226- NewM =
1227- Builder.CreateMemMove (M->getDest (), M->getDestAlign (), CopySource,
1228- CopySourceAlign, M->getLength (), M->isVolatile ());
1248+ NewM = Builder.CreateMemMove (M->getDest (), M->getDestAlign (), CopySource,
1249+ CopySourceAlign, CopyLength, M->isVolatile ());
12291250 else if (M->isForceInlined ())
12301251 // llvm.memcpy may be promoted to llvm.memcpy.inline, but the converse is
12311252 // never allowed since that would allow the latter to be lowered as a call
12321253 // to an external function.
12331254 NewM = Builder.CreateMemCpyInline (M->getDest (), M->getDestAlign (),
1234- CopySource, CopySourceAlign,
1235- M->getLength (), M-> isVolatile ());
1255+ CopySource, CopySourceAlign, CopyLength,
1256+ M->isVolatile ());
12361257 else
12371258 NewM = Builder.CreateMemCpy (M->getDest (), M->getDestAlign (), CopySource,
1238- CopySourceAlign, M->getLength (),
1239- M->isVolatile ());
1259+ CopySourceAlign, CopyLength, M->isVolatile ());
12401260
12411261 NewM->copyMetadata (*M, LLVMContext::MD_DIAssignID);
12421262
0 commit comments