1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +01:00

[SimplifyLibcalls] Realloc(null, N) -> Malloc(N)

Patch by Dávid Bolvanský!

Differential Revision: https://reviews.llvm.org/D45413

llvm-svn: 330259
This commit is contained in:
Sanjay Patel 2018-04-18 14:21:31 +00:00
parent ffb897ed4a
commit cd503329ce
5 changed files with 79 additions and 21 deletions

View File

@ -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

View File

@ -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);

View File

@ -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<Function>(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<Function>(Calloc->stripPointerCasts()))
CI->setCallingConv(F->getCallingConv());
return CI;
}

View File

@ -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<Function>(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<ConstantPointerNull>(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:

View File

@ -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
}