@@ -1156,12 +1156,59 @@ Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilderBase &B) {
1156
1156
return CI->getArgOperand (0 );
1157
1157
}
1158
1158
1159
+ // / Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n).
1160
+ Value *LibCallSimplifier::foldMallocMemset (CallInst *Memset, IRBuilderBase &B) {
1161
+ // This has to be a memset of zeros (bzero).
1162
+ auto *FillValue = dyn_cast<ConstantInt>(Memset->getArgOperand (1 ));
1163
+ if (!FillValue || FillValue->getZExtValue () != 0 )
1164
+ return nullptr ;
1165
+
1166
+ // TODO: We should handle the case where the malloc has more than one use.
1167
+ // This is necessary to optimize common patterns such as when the result of
1168
+ // the malloc is checked against null or when a memset intrinsic is used in
1169
+ // place of a memset library call.
1170
+ auto *Malloc = dyn_cast<CallInst>(Memset->getArgOperand (0 ));
1171
+ if (!Malloc || !Malloc->hasOneUse ())
1172
+ return nullptr ;
1173
+
1174
+ // Is the inner call really malloc()?
1175
+ Function *InnerCallee = Malloc->getCalledFunction ();
1176
+ if (!InnerCallee)
1177
+ return nullptr ;
1178
+
1179
+ LibFunc Func;
1180
+ if (!TLI->getLibFunc (*InnerCallee, Func) || !TLI->has (Func) ||
1181
+ Func != LibFunc_malloc)
1182
+ return nullptr ;
1183
+
1184
+ // The memset must cover the same number of bytes that are malloc'd.
1185
+ if (Memset->getArgOperand (2 ) != Malloc->getArgOperand (0 ))
1186
+ return nullptr ;
1187
+
1188
+ // Replace the malloc with a calloc. We need the data layout to know what the
1189
+ // actual size of a 'size_t' parameter is.
1190
+ B.SetInsertPoint (Malloc->getParent (), ++Malloc->getIterator ());
1191
+ const DataLayout &DL = Malloc->getModule ()->getDataLayout ();
1192
+ IntegerType *SizeType = DL.getIntPtrType (B.GetInsertBlock ()->getContext ());
1193
+ if (Value *Calloc = emitCalloc (ConstantInt::get (SizeType, 1 ),
1194
+ Malloc->getArgOperand (0 ),
1195
+ Malloc->getAttributes (), B, *TLI)) {
1196
+ substituteInParent (Malloc, Calloc);
1197
+ return Calloc;
1198
+ }
1199
+
1200
+ return nullptr ;
1201
+ }
1202
+
1159
1203
Value *LibCallSimplifier::optimizeMemSet (CallInst *CI, IRBuilderBase &B) {
1160
1204
Value *Size = CI->getArgOperand (2 );
1161
1205
annotateNonNullAndDereferenceable (CI, 0 , Size, DL);
1162
1206
if (isa<IntrinsicInst>(CI))
1163
1207
return nullptr ;
1164
1208
1209
+ if (auto *Calloc = foldMallocMemset (CI, B))
1210
+ return Calloc;
1211
+
1165
1212
// memset(p, v, n) -> llvm.memset(align 1 p, v, n)
1166
1213
Value *Val = B.CreateIntCast (CI->getArgOperand (1 ), B.getInt8Ty (), false );
1167
1214
CallInst *NewCI = B.CreateMemSet (CI->getArgOperand (0 ), Val, Size, Align (1 ));
@@ -3019,6 +3066,7 @@ Value *LibCallSimplifier::optimizeCall(CallInst *CI, IRBuilderBase &Builder) {
3019
3066
return optimizeLog (CI, Builder);
3020
3067
case Intrinsic::sqrt:
3021
3068
return optimizeSqrt (CI, Builder);
3069
+ // TODO: Use foldMallocMemset() with memset intrinsic.
3022
3070
case Intrinsic::memset:
3023
3071
return optimizeMemSet (CI, Builder);
3024
3072
case Intrinsic::memcpy:
@@ -3241,6 +3289,8 @@ Value *FortifiedLibCallSimplifier::optimizeMemMoveChk(CallInst *CI,
3241
3289
3242
3290
Value *FortifiedLibCallSimplifier::optimizeMemSetChk (CallInst *CI,
3243
3291
IRBuilderBase &B) {
3292
+ // TODO: Try foldMallocMemset() here.
3293
+
3244
3294
if (isFortifiedCallFoldable (CI, 3 , 2 )) {
3245
3295
Value *Val = B.CreateIntCast (CI->getArgOperand (1 ), B.getInt8Ty (), false );
3246
3296
CallInst *NewCI = B.CreateMemSet (CI->getArgOperand (0 ), Val,
0 commit comments