Index: lib/Transforms/Utils/SimplifyLibCalls.cpp =================================================================== --- lib/Transforms/Utils/SimplifyLibCalls.cpp +++ lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -840,12 +840,8 @@ if (!FillValue || FillValue->getZExtValue() != 0) return nullptr; - // TODO: We should handle the case where the malloc has more than one use. - // This is necessary to optimize common patterns such as when the result of - // the malloc is checked against null or when a memset intrinsic is used in - // place of a memset library call. auto *Malloc = dyn_cast(Memset->getArgOperand(0)); - if (!Malloc || !Malloc->hasOneUse()) + if (!Malloc) return nullptr; // Is the inner call really malloc()? @@ -2219,7 +2215,8 @@ return optimizeLog(CI, Builder); case Intrinsic::sqrt: return optimizeSqrt(CI, Builder); - // TODO: Use foldMallocMemset() with memset intrinsic. + case Intrinsic::memset: + return foldMallocMemset(CI, Builder, *TLI); default: return nullptr; } @@ -2393,7 +2390,8 @@ Value *FortifiedLibCallSimplifier::optimizeMemSetChk(CallInst *CI, IRBuilder<> &B) { - // TODO: Try foldMallocMemset() here. + if (auto *Calloc = foldMallocMemset(CI, B, *TLI)) + return Calloc; if (isFortifiedCallFoldable(CI, 3, 2, false)) { Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); Index: test/Transforms/InstCombine/memset-1.ll =================================================================== --- test/Transforms/InstCombine/memset-1.ll +++ test/Transforms/InstCombine/memset-1.ll @@ -26,6 +26,17 @@ ; CHECK-NEXT: ret i8* %calloc } + +define i8* @malloc_llvmmemset_fold_calloc(i32 %n) #0 { + %call = call i8* @malloc(i32 %n) + call void @llvm.memset.p0i8.i32(i8* %call, i8 0, i32 %n, i32 1, i1 false) + ret i8* %call + +; CHECK-LABEL: @malloc_llvmmemset_fold_calloc( +; CHECK-NEXT: %calloc = call i8* @calloc(i32 1, i32 %n) +; CHECK-NEXT: ret i8* %calloc +} + ; This should not create a calloc and not crash the compiler. ; CHECK-LABEL: @notmalloc_memset ; CHECK-NOT: @calloc @@ -67,6 +78,8 @@ declare noalias i8* @malloc(i32) #1 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) #2 +declare void @llvm.memset.p0i8.i32(i8* nocapture writeonly, i8, i32, i32, i1) #3 +declare i8* @calloc(i32, i32) #4 attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind }