diff options
| author | Chris Lattner <sabre@nondot.org> | 2011-04-17 00:40:24 +0000 |
|---|---|---|
| committer | Chris Lattner <sabre@nondot.org> | 2011-04-17 00:40:24 +0000 |
| commit | 30107ed600da4cd3a5bbb5d70cd6e97b618fff38 (patch) | |
| tree | a72a8fd2b52eea827543e569054af05728bd2f1c | |
| parent | 55b0acd624a3c26b2e2510934997cd98ddbd126f (diff) | |
| download | bcm5719-llvm-30107ed600da4cd3a5bbb5d70cd6e97b618fff38.tar.gz bcm5719-llvm-30107ed600da4cd3a5bbb5d70cd6e97b618fff38.zip | |
fold memcpy/set/move_chk to llvm.memcpy/set/move when the sizes
are trivial. This exposes opportunities earlier, and allows fastisel
to do good things with these at -O0.
This addresses rdar://9289468 - clang doesn't fold memset_chk at -O0
llvm-svn: 129651
| -rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 51 | ||||
| -rw-r--r-- | clang/test/CodeGen/builtin-memfns.c | 29 | ||||
| -rw-r--r-- | clang/test/CodeGen/builtinmemcpy.c | 3 |
3 files changed, 78 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 97b93d50300..51d9eebaba1 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -543,6 +543,22 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, return RValue::get(Address); } + case Builtin::BI__builtin___memcpy_chk: { + // fold __builtin_memcpy_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Dest = EmitScalarExpr(E->getArg(0)); + Value *Src = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemCpy(Dest, Src, SizeVal, 1, false); + return RValue::get(0); + } + case Builtin::BI__builtin_objc_memmove_collectable: { Value *Address = EmitScalarExpr(E->getArg(0)); Value *SrcAddr = EmitScalarExpr(E->getArg(1)); @@ -551,7 +567,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Address, SrcAddr, SizeVal); return RValue::get(Address); } - + + case Builtin::BI__builtin___memmove_chk: { + // fold __builtin_memmove_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Dest = EmitScalarExpr(E->getArg(0)); + Value *Src = EmitScalarExpr(E->getArg(1)); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemMove(Dest, Src, SizeVal, 1, false); + return RValue::get(0); + } + case Builtin::BImemmove: case Builtin::BI__builtin_memmove: { Value *Address = EmitScalarExpr(E->getArg(0)); @@ -569,6 +601,23 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD, Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false); return RValue::get(Address); } + case Builtin::BI__builtin___memset_chk: { + // fold __builtin_memset_chk(x, y, cst1, cst2) to memset iff cst1<=cst2. + if (!E->getArg(2)->isEvaluatable(CGM.getContext()) || + !E->getArg(3)->isEvaluatable(CGM.getContext())) + break; + llvm::APSInt Size = E->getArg(2)->EvaluateAsInt(CGM.getContext()); + llvm::APSInt DstSize = E->getArg(3)->EvaluateAsInt(CGM.getContext()); + if (Size.ugt(DstSize)) + break; + Value *Address = EmitScalarExpr(E->getArg(0)); + Value *ByteVal = Builder.CreateTrunc(EmitScalarExpr(E->getArg(1)), + Builder.getInt8Ty()); + Value *SizeVal = llvm::ConstantInt::get(Builder.getContext(), Size); + Builder.CreateMemSet(Address, ByteVal, SizeVal, 1, false); + + return RValue::get(0); + } case Builtin::BI__builtin_dwarf_cfa: { // The offset in bytes from the first argument to the CFA. // diff --git a/clang/test/CodeGen/builtin-memfns.c b/clang/test/CodeGen/builtin-memfns.c index e8c407fd6f2..2ea67936547 100644 --- a/clang/test/CodeGen/builtin-memfns.c +++ b/clang/test/CodeGen/builtin-memfns.c @@ -1,12 +1,13 @@ // RUN: %clang_cc1 -triple i386-pc-linux-gnu -emit-llvm < %s| FileCheck %s +// CHECK: @test1 // CHECK: call void @llvm.memset.p0i8.i32 // CHECK: call void @llvm.memset.p0i8.i32 // CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 // CHECK: call void @llvm.memmove.p0i8.p0i8.i32 // CHECK-NOT: __builtin // CHECK: ret -int main(int argc, char **argv) { +int test1(int argc, char **argv) { unsigned char a = 0x11223344; unsigned char b = 0x11223344; __builtin_bzero(&a, sizeof(a)); @@ -15,3 +16,29 @@ int main(int argc, char **argv) { __builtin_memmove(&a, &b, sizeof(a)); return 0; } + +// rdar://9289468 + +// CHECK: @test2 +// CHECK: call void @llvm.memcpy.p0i8.p0i8.i32 +char* test2(char* a, char* b) { + return __builtin_memcpy(a, b, 4); +} + +// CHECK: @test3 +// CHECK: call void @llvm.memset +void test3(char *P) { + __builtin___memset_chk(P, 42, 128, 128); +} + +// CHECK: @test4 +// CHECK: call void @llvm.memcpy +void test4(char *P, char *Q) { + __builtin___memcpy_chk(P, Q, 128, 128); +} + +// CHECK: @test5 +// CHECK: call void @llvm.memmove +void test5(char *P, char *Q) { + __builtin___memmove_chk(P, Q, 128, 128); +} diff --git a/clang/test/CodeGen/builtinmemcpy.c b/clang/test/CodeGen/builtinmemcpy.c deleted file mode 100644 index 93253c5a8a4..00000000000 --- a/clang/test/CodeGen/builtinmemcpy.c +++ /dev/null @@ -1,3 +0,0 @@ -// RUN: %clang_cc1 -emit-llvm < %s -o - | grep "llvm.memcpy" - -char* x(char* a, char* b) {return __builtin_memcpy(a, b, 4);} |

