@@ -107,6 +107,9 @@ struct MemsetRange {
107
107
108
108
} // end anonymous namespace
109
109
110
+ static bool overreadUndefContents (MemorySSA *MSSA, MemCpyInst *MemCpy,
111
+ MemIntrinsic *MemSrc, BatchAAResults &BAA);
112
+
110
113
bool MemsetRange::isProfitableToUseMemset (const DataLayout &DL) const {
111
114
// If we found more than 4 stores to merge or 16 bytes, use memset.
112
115
if (TheStores.size () >= 4 || End - Start >= 16 )
@@ -1129,14 +1132,28 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
1129
1132
MForwardOffset = *Offset;
1130
1133
}
1131
1134
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) {
1135
1141
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
+ }
1140
1157
}
1141
1158
1142
1159
IRBuilder<> Builder (M);
@@ -1152,9 +1169,13 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
1152
1169
eraseInstruction (NewCopySource);
1153
1170
});
1154
1171
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
+ }
1158
1179
1159
1180
// When the forwarding offset is greater than 0, we transform
1160
1181
// memcpy(d1 <- s1)
@@ -1223,20 +1244,18 @@ bool MemCpyOptPass::processMemCpyMemCpyDependence(MemCpyInst *M,
1223
1244
// example we could be moving from movaps -> movq on x86.
1224
1245
Instruction *NewM;
1225
1246
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 ());
1229
1249
else if (M->isForceInlined ())
1230
1250
// llvm.memcpy may be promoted to llvm.memcpy.inline, but the converse is
1231
1251
// never allowed since that would allow the latter to be lowered as a call
1232
1252
// to an external function.
1233
1253
NewM = Builder.CreateMemCpyInline (M->getDest (), M->getDestAlign (),
1234
- CopySource, CopySourceAlign,
1235
- M->getLength (), M-> isVolatile ());
1254
+ CopySource, CopySourceAlign, CopyLength,
1255
+ M->isVolatile ());
1236
1256
else
1237
1257
NewM = Builder.CreateMemCpy (M->getDest (), M->getDestAlign (), CopySource,
1238
- CopySourceAlign, M->getLength (),
1239
- M->isVolatile ());
1258
+ CopySourceAlign, CopyLength, M->isVolatile ());
1240
1259
1241
1260
NewM->copyMetadata (*M, LLVMContext::MD_DIAssignID);
1242
1261
0 commit comments