From: Chris Lattner Date: Sat, 28 Feb 2009 18:18:58 +0000 (+0000) Subject: after going around in circles a few times, finally cave and emit structure X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ca4fc2c2620e184e8b96845a87b19d54f9e045c1;p=clang after going around in circles a few times, finally cave and emit structure copies with memcpy instead of memmove. This matches what GCC does and if it causes a problem with a particular libc we can always fix it with a target hook. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65699 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index e2f5c79d99..b0596e2fee 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -518,7 +518,16 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, llvm::Value *SrcPtr, QualType Ty) { assert(!Ty->isAnyComplexType() && "Shouldn't happen for complex"); - // Aggregate assignment turns into llvm.memmove. + // Aggregate assignment turns into llvm.memset. This is almost valid per + // C99 6.5.16.1p3, which states "If the value being stored in an object is + // read from another object that overlaps in anyway the storage of the first + // object, then the overlap shall be exact and the two objects shall have + // qualified or unqualified versions of a compatible type." + // + // memset is not defined if the source and destination pointers are exactly + // equal, but other compilers do this optimization, and almost every memcpy + // implementation handles this case safely. If there is a libc that does not + // safely handle this, we can add a target hook. const llvm::Type *BP = llvm::PointerType::getUnqual(llvm::Type::Int8Ty); if (DestPtr->getType() != BP) DestPtr = Builder.CreateBitCast(DestPtr, BP, "tmp"); @@ -531,7 +540,7 @@ void CodeGenFunction::EmitAggregateCopy(llvm::Value *DestPtr, // FIXME: Handle variable sized types. const llvm::Type *IntPtr = llvm::IntegerType::get(LLVMPointerWidth); - Builder.CreateCall4(CGM.getMemMoveFn(), + Builder.CreateCall4(CGM.getMemCpyFn(), DestPtr, SrcPtr, // TypeInfo.first describes size in bits. llvm::ConstantInt::get(IntPtr, TypeInfo.first/8), diff --git a/test/CodeGen/struct-copy.c b/test/CodeGen/struct-copy.c new file mode 100644 index 0000000000..a45e37a30f --- /dev/null +++ b/test/CodeGen/struct-copy.c @@ -0,0 +1,7 @@ +// RUN: clang -emit-llvm %s -o - | grep 'call.*llvm.memcpy' +struct x { int a[100]; }; + + +void foo(struct x *P, struct x *Q) { + *P = *Q; +}