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()? @@ -853,6 +849,10 @@ if (!InnerCallee) return nullptr; + // Check if non-intristic malloc has more than one use + if (!InnerCallee->isIntrinsic() && !Malloc->hasOneUse()) + return nullptr; + LibFunc Func; if (!TLI.getLibFunc(*InnerCallee, Func) || !TLI.has(Func) || Func != LibFunc_malloc) @@ -883,6 +883,10 @@ if (auto *Calloc = foldMallocMemset(CI, B, *TLI)) return Calloc; + if (CI->getCalledFunction()->isIntrinsic()) { + return nullptr; + } + // memset(p, v, n) -> llvm.memset(align 1 p, v, n) Value *Val = B.CreateIntCast(CI->getArgOperand(1), B.getInt8Ty(), false); B.CreateMemSet(CI->getArgOperand(0), Val, CI->getArgOperand(2), 1); @@ -2219,7 +2223,8 @@ return optimizeLog(CI, Builder); case Intrinsic::sqrt: return optimizeSqrt(CI, Builder); - // TODO: Use foldMallocMemset() with memset intrinsic. + case Intrinsic::memset: + return optimizeMemSet(CI, Builder); default: return nullptr; } Index: test/Transforms/InstCombine/memset-1.ll =================================================================== --- test/Transforms/InstCombine/memset-1.ll +++ test/Transforms/InstCombine/memset-1.ll @@ -102,6 +102,16 @@ ret i8* %memset } +define i8* @memset_intristic_malloc(i32 %n) #0 { +; CHECK-LABEL: @memset_intristic_malloc( +; CHECK-NEXT: [[CALLOC:%.*]] = call i8* @calloc(i32 1, i32 [[N:%.*]]) +; CHECK-NEXT: ret i8* [[CALLOC]] +; + %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 +} + attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind } attributes #2 = { nounwind readnone }