From 3bcaa8ac95a72487cfeab4adbc076ddf89ad5673 Mon Sep 17 00:00:00 2001 From: Eric Christopher Date: Fri, 20 Nov 2009 19:57:37 +0000 Subject: [PATCH] Add some rough optimizations for checking routines. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89479 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SimplifyLibCalls.cpp | 131 ++++++++++++++++++++++++++--- 1 file changed, 119 insertions(+), 12 deletions(-) diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 611505ef363..92af5bb2da6 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -81,6 +81,9 @@ public: Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len, unsigned Align, IRBuilder<> &B); + Value *EmitMemMove(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B); + /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B); @@ -160,6 +163,22 @@ Value *LibCallOptimization::EmitMemCpy(Value *Dst, Value *Src, Value *Len, ConstantInt::get(Type::getInt32Ty(*Context), Align)); } +/// EmitMemMOve - Emit a call to the memmove function to the builder. This +/// always expects that the size has type 'intptr_t' and Dst/Src are pointers. +Value *LibCallOptimization::EmitMemMove(Value *Dst, Value *Src, Value *Len, + unsigned Align, IRBuilder<> &B) { + Module *M = Caller->getParent(); + Intrinsic::ID IID = Intrinsic::memmove; + const Type *Tys[1]; + Tys[0] = TD->getIntPtrType(*Context); + Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1); + Value *Dst = CastToCStr(CI->getOperand(1), B); + Value *Src = CastToCStr(CI->getOperand(2), B); + Value *Size = CI->getOperand(3); + Value *Align = ConstantInt::get(Type::getInt32Ty(*Context), 1); + return B.CreateCall4(MemMove, Dst, Src, Size, Align); +} + /// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is /// a pointer, Val is an i32 value, and Len is an 'intptr_t' value. Value *LibCallOptimization::EmitMemChr(Value *Ptr, Value *Val, @@ -1010,16 +1029,7 @@ struct MemMoveOpt : public LibCallOptimization { return 0; // memmove(x, y, n) -> llvm.memmove(x, y, n, 1) - Module *M = Caller->getParent(); - Intrinsic::ID IID = Intrinsic::memmove; - const Type *Tys[1]; - Tys[0] = TD->getIntPtrType(*Context); - Value *MemMove = Intrinsic::getDeclaration(M, IID, Tys, 1); - Value *Dst = CastToCStr(CI->getOperand(1), B); - Value *Src = CastToCStr(CI->getOperand(2), B); - Value *Size = CI->getOperand(3); - Value *Align = ConstantInt::get(Type::getInt32Ty(*Context), 1); - B.CreateCall4(MemMove, Dst, Src, Size, Align); + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); return CI->getOperand(1); } }; @@ -1048,6 +1058,96 @@ struct MemSetOpt : public LibCallOptimization { }; //===----------------------------------------------------------------------===// +// Object Size Checking Optimizations +//===----------------------------------------------------------------------===// +//===---------------------------------------===// +// 'memcpy_chk' Optimizations + +struct MemCpyChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), 1, B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'memset_chk' Optimizations + +struct MemSetChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + Value *Val = B.CreateIntCast(CI->getOperand(2), Type::getInt8Ty(*Context), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===---------------------------------------===// +// 'memmove_chk' Optimizations + +struct MemMoveChkOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + // These optimizations require TargetData. + if (!TD) return 0; + + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 4 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + !isa(FT->getParamType(3)) || + FT->getParamType(2) != TD->getIntPtrType(*Context)) + return 0; + + ConstantInt *SizeCI = dyn_cast(CI->getOperand(4)); + if (!SizeCI) + return 0; + if (SizeCI->isAllOnesValue()) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B); + return CI->getOperand(1); + } + + return 0; + } +}; + +//===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1586,7 +1686,10 @@ namespace { // Formatting and IO Optimizations SPrintFOpt SPrintF; PrintFOpt PrintF; FWriteOpt FWrite; FPutsOpt FPuts; FPrintFOpt FPrintF; + + // Object Size Checking SizeOpt ObjectSize; + MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk; bool Modified; // This is only used by doInitialization. public: @@ -1693,8 +1796,12 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["fputs"] = &FPuts; Optimizations["fprintf"] = &FPrintF; - // Miscellaneous - Optimizations["llvm.objectsize"] = &ObjectSize; + // Object Size Checking + Optimizations["llvm.objectsize.i32"] = &ObjectSize; + Optimizations["llvm.objectsize.i64"] = &ObjectSize; + Optimizations["__memcpy_chk"] = &MemCpyChk; + Optimizations["__memset_chk"] = &MemSetChk; + Optimizations["__memmove_chk"] = &MemMoveChk; } -- 2.11.0