[cfe-dev] C++ AST Question
Chris Lattner
clattner at apple.com
Mon Jun 28 17:55:38 PDT 2010
On Jun 27, 2010, at 1:36 AM, Eli Friedman wrote:
>> After diving into it, the memcpy is being made by CodeGenFunction::EmitCXXConstructorCall, so I came up with this patch:
>
> Stop right there; the behavior here is exactly the same in C mode,
> where the CXXConstructorCall clearly doesn't exist. You're not going
> to get anywhere examining it...
Good point, that occurred to me in the middle of the night :)
> Take a look at what happens in CodeGenFunction::EmitCall (the version
> in CGExpr.cpp). The copy already exists after EmitCallArgs runs:
> since it isn't aware that the ABI is going to pass the struct by
> value, and you can't just pass the pointer D into foo(), it
> immediately make a copy to ensure correct behavior.
Ok, right. Specifically, we end up down in the bowels of:
RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
if (ArgType->isReferenceType())
return EmitReferenceBindingToExpr(E, /*InitializedDecl=*/0);
return EmitAnyExprToTemp(E);
}
EmitAnyExprToTemp(E) is emitting the extra copy. The fix is to emit aggregates as l-values, but this won't work for the CallArgList data structure that Daniel has set up. Daniel, what do you think is the right approach here? Here's a simple C example:
struct DeclGroup {
long NumDecls;
long Y;
};
long foo(struct DeclGroup D);
void bar(struct DeclGroup *D) {
foo(*D);
}
Compiles to:
define void @bar(%struct.DeclGroup* %D) {
entry:
%D.addr = alloca %struct.DeclGroup*, align 8 ; <%struct.DeclGroup**> [#uses=2]
%agg.tmp = alloca %struct.DeclGroup, align 8 ; <%struct.DeclGroup*> [#uses=1]
%allocapt = bitcast i32 undef to i32 ; <i32> [#uses=0]
store %struct.DeclGroup* %D, %struct.DeclGroup** %D.addr
%tmp = load %struct.DeclGroup** %D.addr ; <%struct.DeclGroup*> [#uses=1]
%tmp1 = bitcast %struct.DeclGroup* %agg.tmp to i8* ; <i8*> [#uses=1]
%tmp2 = bitcast %struct.DeclGroup* %tmp to i8* ; <i8*> [#uses=1]
call void @llvm.memcpy.p0i8.p0i8.i64(i8* %tmp1, i8* %tmp2, i64 16, i32 8, i1 false)
}
I want to kill off the extra temporary + memcpy.
-Chris
More information about the cfe-dev
mailing list