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:
parent
ffb897ed4a
commit
cd503329ce
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
24
test/Transforms/InstCombine/realloc.ll
Normal file
24
test/Transforms/InstCombine/realloc.ll
Normal 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user