From d83ae7d698248958e157aeeaca9fb114bf1e2b60 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Sun, 30 Nov 2008 08:32:11 +0000 Subject: [PATCH] Optimize memmove and memset into the LLVM builtins. Note that these only show up in code from front-ends besides llvm-gcc, like clang. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@60287 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/SimplifyLibCalls.cpp | 61 +++++++++++++++++++-- test/Transforms/SimplifyLibCalls/memmove.ll | 12 ++++ test/Transforms/SimplifyLibCalls/memset.ll | 12 ++++ 3 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 test/Transforms/SimplifyLibCalls/memmove.ll create mode 100644 test/Transforms/SimplifyLibCalls/memset.ll diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp index 89527477a80..07c8d94860c 100644 --- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp +++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp @@ -707,6 +707,60 @@ struct VISIBILITY_HIDDEN MemCpyOpt : public LibCallOptimization { } }; +//===---------------------------------------===// +// 'memmove' Optimizations + +struct VISIBILITY_HIDDEN MemMoveOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + !isa(FT->getParamType(1)) || + FT->getParamType(2) != TD->getIntPtrType()) + 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(); + 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::Int32Ty, 1); + B.CreateCall4(MemMove, Dst, Src, Size, Align); + return CI->getOperand(1); + } +}; + +//===---------------------------------------===// +// 'memset' Optimizations + +struct VISIBILITY_HIDDEN MemSetOpt : public LibCallOptimization { + virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) { + const FunctionType *FT = Callee->getFunctionType(); + if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) || + !isa(FT->getParamType(0)) || + FT->getParamType(1) != TD->getIntPtrType() || + FT->getParamType(2) != TD->getIntPtrType()) + return 0; + + // memset(p, v, n) -> llvm.memset(p, v, n, 1) + Module *M = Caller->getParent(); + Intrinsic::ID IID = Intrinsic::memset; + const Type *Tys[1]; + Tys[0] = TD->getIntPtrType(); + Value *MemSet = Intrinsic::getDeclaration(M, IID, Tys, 1); + Value *Dst = CastToCStr(CI->getOperand(1), B); + Value *Val = B.CreateTrunc(CI->getOperand(2), Type::Int8Ty); + Value *Size = CI->getOperand(3); + Value *Align = ConstantInt::get(Type::Int32Ty, 1); + B.CreateCall4(MemSet, Dst, Val, Size, Align); + return CI->getOperand(1); + } +}; + //===----------------------------------------------------------------------===// // Math Library Optimizations //===----------------------------------------------------------------------===// @@ -1197,6 +1251,7 @@ namespace { // String and Memory LibCall Optimizations StrCatOpt StrCat; StrChrOpt StrChr; StrCmpOpt StrCmp; StrNCmpOpt StrNCmp; StrCpyOpt StrCpy; StrLenOpt StrLen; MemCmpOpt MemCmp; MemCpyOpt MemCpy; + MemMoveOpt MemMove; MemSetOpt MemSet; // Math Library Optimizations PowOpt Pow; Exp2Opt Exp2; UnaryDoubleFPOpt UnaryDoubleFP; // Integer Optimizations @@ -1242,6 +1297,8 @@ void SimplifyLibCalls::InitOptimizations() { Optimizations["strlen"] = &StrLen; Optimizations["memcmp"] = &MemCmp; Optimizations["memcpy"] = &MemCpy; + Optimizations["memmove"] = &MemMove; + Optimizations["memset"] = &MemSet; // Math Library Optimizations Optimizations["powf"] = &Pow; @@ -1386,10 +1443,6 @@ bool SimplifyLibCalls::runOnFunction(Function &F) { // * memcmp(x,y,l) -> cnst // (if all arguments are constant and strlen(x) <= l and strlen(y) <= l) // -// memmove: -// * memmove(d,s,l,a) -> memcpy(d,s,l,a) -// (if s is a global constant array) -// // pow, powf, powl: // * pow(exp(x),y) -> exp(x*y) // * pow(sqrt(x),y) -> pow(x,y*0.5) diff --git a/test/Transforms/SimplifyLibCalls/memmove.ll b/test/Transforms/SimplifyLibCalls/memmove.ll new file mode 100644 index 00000000000..d960960c9c2 --- /dev/null +++ b/test/Transforms/SimplifyLibCalls/memmove.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep {llvm.memmove} +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" +target triple = "i686-pc-linux-gnu" + +define i8* @test(i8* %a, i8* %b, i32 %x) { +entry: + %call = call i8* @memmove(i8* %a, i8* %b, i32 %x ) + ret i8* %call +} + +declare i8* @memmove(i8*,i8*,i32) + diff --git a/test/Transforms/SimplifyLibCalls/memset.ll b/test/Transforms/SimplifyLibCalls/memset.ll new file mode 100644 index 00000000000..0c109154a3e --- /dev/null +++ b/test/Transforms/SimplifyLibCalls/memset.ll @@ -0,0 +1,12 @@ +; RUN: llvm-as < %s | opt -simplify-libcalls | llvm-dis | grep {llvm.memset} +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:32:32" +target triple = "i686-pc-linux-gnu" + +define i8* @test(i8* %a, i32 %b, i32 %x) { +entry: + %call = call i8* @memset(i8* %a, i32 %b, i32 %x ) + ret i8* %call +} + +declare i8* @memset(i8*,i32,i32) + -- 2.34.1