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,27 @@ ; CHECK-NEXT: ret i8* %calloc } + +define i8* @pr45344(i32 %n) #0 { + %n.addr = alloca i32, align 4 + %b = alloca i8*, align 8 + store i32 %n, i32* %n.addr, align 4 + %0 = load i32, i32* %n.addr, align 4 + %call = call i8* @malloc(i32 %0) + store i8* %call, i8** %b, align 8 + %1 = load i8*, i8** %b, align 8 + %2 = load i32, i32* %n.addr, align 4 + %conv = sext i32 %2 to i64 + call void @llvm.memset.p0i8.i64(i8* %1, i8 0, i64 %conv, i32 1, i1 false) + %3 = load i8*, i8** %b, align 8 + ret i8* %3 + +; CHECK-LABEL: @pr45344( +; CHECK-NEXT: %conv = sext i32 %n to i64 +; CHECK-NEXT: %calloc = tail call i8* @calloc(i64 1, i64 %conv) #1 +; 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 +88,7 @@ declare noalias i8* @malloc(i32) #1 declare i64 @llvm.objectsize.i64.p0i8(i8*, i1) #2 +declare void @llvm.memset.p0i8.i64(i8* nocapture writeonly, i8, i64, i32, i1) #3 attributes #0 = { nounwind ssp uwtable } attributes #1 = { nounwind }