From cd503329cef22364e65b75540bb73f804173ad43 Mon Sep 17 00:00:00 2001 From: Sanjay Patel Date: Wed, 18 Apr 2018 14:21:31 +0000 Subject: [PATCH] [SimplifyLibcalls] Realloc(null, N) -> Malloc(N) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Patch by Dávid Bolvanský! Differential Revision: https://reviews.llvm.org/D45413 llvm-svn: 330259 --- include/llvm/Transforms/Utils/BuildLibCalls.h | 8 ++++ .../llvm/Transforms/Utils/SimplifyLibCalls.h | 1 + lib/Transforms/Utils/BuildLibCalls.cpp | 37 +++++++++++++++++++ lib/Transforms/Utils/SimplifyLibCalls.cpp | 30 +++++---------- test/Transforms/InstCombine/realloc.ll | 24 ++++++++++++ 5 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 test/Transforms/InstCombine/realloc.ll diff --git a/include/llvm/Transforms/Utils/BuildLibCalls.h b/include/llvm/Transforms/Utils/BuildLibCalls.h index 3a71559a93f..e38f1ac0f68 100644 --- a/include/llvm/Transforms/Utils/BuildLibCalls.h +++ b/include/llvm/Transforms/Utils/BuildLibCalls.h @@ -120,6 +120,14 @@ namespace llvm { /// Size is an 'intptr_t', and File is a pointer to FILE. Value *emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, const DataLayout &DL, const TargetLibraryInfo *TLI); + + /// Emit a call to the malloc function. + Value *emitMalloc(Value *Num, IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI); + + /// Emit a call to the calloc function. + Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs, + IRBuilder<> &B, const TargetLibraryInfo &TLI); } #endif diff --git a/include/llvm/Transforms/Utils/SimplifyLibCalls.h b/include/llvm/Transforms/Utils/SimplifyLibCalls.h index 73a62f59203..eaed60b78e7 100644 --- a/include/llvm/Transforms/Utils/SimplifyLibCalls.h +++ b/include/llvm/Transforms/Utils/SimplifyLibCalls.h @@ -124,6 +124,7 @@ private: Value *optimizeMemCpy(CallInst *CI, IRBuilder<> &B); Value *optimizeMemMove(CallInst *CI, IRBuilder<> &B); Value *optimizeMemSet(CallInst *CI, IRBuilder<> &B); + Value *optimizeRealloc(CallInst *CI, IRBuilder<> &B); Value *optimizeWcslen(CallInst *CI, IRBuilder<> &B); // Wrapper for all String/Memory Library Call Optimizations Value *optimizeStringMemoryLibCall(CallInst *CI, IRBuilder<> &B); diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp index 24af7c463f4..7de2c1cc8d5 100644 --- a/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/lib/Transforms/Utils/BuildLibCalls.cpp @@ -1037,3 +1037,40 @@ Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B, CI->setCallingConv(Fn->getCallingConv()); return CI; } + +Value *llvm::emitMalloc(Value *Num, IRBuilder<> &B, const DataLayout &DL, + const TargetLibraryInfo *TLI) { + if (!TLI->has(LibFunc_malloc)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); + LLVMContext &Context = B.GetInsertBlock()->getContext(); + Value *Malloc = M->getOrInsertFunction("malloc", B.getInt8PtrTy(), + DL.getIntPtrType(Context)); + inferLibFuncAttributes(*M->getFunction("malloc"), *TLI); + CallInst *CI = B.CreateCall(Malloc, Num, "malloc"); + + if (const Function *F = dyn_cast(Malloc->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} + +Value *llvm::emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs, + IRBuilder<> &B, const TargetLibraryInfo &TLI) { + if (!TLI.has(LibFunc_calloc)) + return nullptr; + + Module *M = B.GetInsertBlock()->getModule(); + const DataLayout &DL = M->getDataLayout(); + IntegerType *PtrType = DL.getIntPtrType((B.GetInsertBlock()->getContext())); + Value *Calloc = M->getOrInsertFunction("calloc", Attrs, B.getInt8PtrTy(), + PtrType, PtrType); + inferLibFuncAttributes(*M->getFunction("calloc"), TLI); + CallInst *CI = B.CreateCall(Calloc, {Num, Size}, "calloc"); + + if (const auto *F = dyn_cast(Calloc->stripPointerCasts())) + CI->setCallingConv(F->getCallingConv()); + + return CI; +} diff --git a/lib/Transforms/Utils/SimplifyLibCalls.cpp b/lib/Transforms/Utils/SimplifyLibCalls.cpp index 6c68b88adc6..e65ecc55c83 100644 --- a/lib/Transforms/Utils/SimplifyLibCalls.cpp +++ b/lib/Transforms/Utils/SimplifyLibCalls.cpp @@ -811,27 +811,6 @@ Value *LibCallSimplifier::optimizeMemMove(CallInst *CI, IRBuilder<> &B) { return CI->getArgOperand(0); } -// TODO: Does this belong in BuildLibCalls or should all of those similar -// functions be moved here? -static Value *emitCalloc(Value *Num, Value *Size, const AttributeList &Attrs, - IRBuilder<> &B, const TargetLibraryInfo &TLI) { - LibFunc Func; - if (!TLI.getLibFunc("calloc", Func) || !TLI.has(Func)) - return nullptr; - - Module *M = B.GetInsertBlock()->getModule(); - const DataLayout &DL = M->getDataLayout(); - IntegerType *PtrType = DL.getIntPtrType((B.GetInsertBlock()->getContext())); - Value *Calloc = M->getOrInsertFunction("calloc", Attrs, B.getInt8PtrTy(), - PtrType, PtrType); - CallInst *CI = B.CreateCall(Calloc, { Num, Size }, "calloc"); - - if (const auto *F = dyn_cast(Calloc->stripPointerCasts())) - CI->setCallingConv(F->getCallingConv()); - - return CI; -} - /// Fold memset[_chk](malloc(n), 0, n) --> calloc(1, n). static Value *foldMallocMemset(CallInst *Memset, IRBuilder<> &B, const TargetLibraryInfo &TLI) { @@ -889,6 +868,13 @@ Value *LibCallSimplifier::optimizeMemSet(CallInst *CI, IRBuilder<> &B) { return CI->getArgOperand(0); } +Value *LibCallSimplifier::optimizeRealloc(CallInst *CI, IRBuilder<> &B) { + if (isa(CI->getArgOperand(0))) + return emitMalloc(CI->getArgOperand(1), B, DL, TLI); + + return nullptr; +} + //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -2080,6 +2066,8 @@ Value *LibCallSimplifier::optimizeStringMemoryLibCall(CallInst *CI, return optimizeMemMove(CI, Builder); case LibFunc_memset: return optimizeMemSet(CI, Builder); + case LibFunc_realloc: + return optimizeRealloc(CI, Builder); case LibFunc_wcslen: return optimizeWcslen(CI, Builder); default: diff --git a/test/Transforms/InstCombine/realloc.ll b/test/Transforms/InstCombine/realloc.ll new file mode 100644 index 00000000000..22f37f1d2fa --- /dev/null +++ b/test/Transforms/InstCombine/realloc.ll @@ -0,0 +1,24 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt < %s -instcombine -S | FileCheck %s + +declare i8* @realloc(i8*, i64) #1 +declare noalias i8* @malloc(i64) #1 + + +define i8* @realloc_null_ptr() #0 { +; CHECK-LABEL: @realloc_null_ptr( +; CHECK-NEXT: [[MALLOC:%.*]] = call i8* @malloc(i64 100) +; CHECK-NEXT: ret i8* [[MALLOC]] +; + %call = call i8* @realloc(i8* null, i64 100) #2 + ret i8* %call +} + +define i8* @realloc_unknown_ptr(i8* %ptr) #0 { +; CHECK-LABEL: @realloc_unknown_ptr( +; CHECK-NEXT: [[CALL:%.*]] = call i8* @realloc(i8* [[PTR:%.*]], i64 100) +; CHECK-NEXT: ret i8* [[CALL]] +; + %call = call i8* @realloc(i8* %ptr, i64 100) #2 + ret i8* %call +}