@@ -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,28 @@ 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)
1139-       return  false ;
1142+     auto  *MLen = dyn_cast<ConstantInt>(CopyLength);
1143+     if  (!MDepLen || !MLen)
1144+       return  false ; //  This could be converted to a runtime test (%CopyLength =
1145+                     //  min(max(0, MDepLen - MForwardOffset), MLen)), but it is
1146+                     //  unclear if that is useful
1147+     if  (MDepLen->getZExtValue () < MLen->getZExtValue () + MForwardOffset) {
1148+       if  (!overreadUndefContents (MSSA, M, MDep, BAA))
1149+         return  false ;
1150+       if  (MDepLen->getZExtValue () <= (uint64_t )MForwardOffset)
1151+         return  false ; //  Should not reach here (there is obviously no aliasing
1152+                       //  with MDep), so just bail in case it had incomplete info
1153+                       //  somehow
1154+       CopyLength = ConstantInt::get (CopyLength->getType (),
1155+                                     MDepLen->getZExtValue () - MForwardOffset);
1156+     }
11401157  }
11411158
11421159  IRBuilder<> Builder (M);
@@ -1152,9 +1169,13 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
11521169      eraseInstruction (NewCopySource);
11531170  });
11541171  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 );
1172+   auto  MCopyLoc = MemoryLocation::getForSource (MDep);
1173+   //  Truncate the size of the MDep access to just the bytes read
1174+   if  (MDep->getLength () != CopyLength) {
1175+     auto  ConstLength = cast<ConstantInt>(CopyLength);
1176+     MCopyLoc = MCopyLoc.getWithNewSize (
1177+         LocationSize::precise (ConstLength->getZExtValue ()));
1178+   }
11581179
11591180  //  When the forwarding offset is greater than 0, we transform
11601181  //     memcpy(d1 <- s1)
@@ -1223,20 +1244,18 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
12231244  //  example we could be moving from movaps -> movq on x86.
12241245  Instruction *NewM;
12251246  if  (UseMemMove)
1226-     NewM =
1227-         Builder.CreateMemMove (M->getDest (), M->getDestAlign (), CopySource,
1228-                               CopySourceAlign, M->getLength (), M->isVolatile ());
1247+     NewM = Builder.CreateMemMove (M->getDest (), M->getDestAlign (), CopySource,
1248+                                  CopySourceAlign, CopyLength, M->isVolatile ());
12291249  else  if  (M->isForceInlined ())
12301250    //  llvm.memcpy may be promoted to llvm.memcpy.inline, but the converse is
12311251    //  never allowed since that would allow the latter to be lowered as a call
12321252    //  to an external function.
12331253    NewM = Builder.CreateMemCpyInline (M->getDest (), M->getDestAlign (),
1234-                                       CopySource, CopySourceAlign,
1235-                                       M->getLength (), M-> isVolatile ());
1254+                                       CopySource, CopySourceAlign, CopyLength, 
1255+                                       M->isVolatile ());
12361256  else 
12371257    NewM = Builder.CreateMemCpy (M->getDest (), M->getDestAlign (), CopySource,
1238-                                 CopySourceAlign, M->getLength (),
1239-                                 M->isVolatile ());
1258+                                 CopySourceAlign, CopyLength, M->isVolatile ());
12401259
12411260  NewM->copyMetadata (*M, LLVMContext::MD_DIAssignID);
12421261
0 commit comments