I have to create two versions of the same function: one with all parameters listed, one with parameters passed as a struct. The number of parameters is arbitrary. I implement the functionality in only one of them, the other is just calling it with expanded parameters or initialized structure.
Is there a difference in the overhead between the two versions below?
Version 1
int functionWithStructure(MyStructure a)
{
return functionWithMultipleParams(a.Myparam1, a.Myparam2);
}
int functionWithMultipleParams(int param1, int param2)
{
return /* implement something */;
}
Version 2
int functionWithMultipleParams(int param1, int param2)
{
return functionWithStructure((MyStructure) {param1, param2});
}
int functionWithStructure(MyStructure a)
{
return /* implement something */;
}
You can't say that one version is always better than the other. Sometimes it is better to pack parameters into a
struct, and sometimes it is worse.In the x86_64 ABI, there is a difference between passing 2x
intand a singlestructparameter.intis passed via a separate registeredi,esistructmembers are packed into a single registerrdiAs a rule of thumb, a
structis better when we perform operations with the wholestruct(like passing it to other functions), whereas separate parameters are better when using them in separate ways.Positive Cost
structWhich produces: (GCC 13
-O2)You can see that
sumsimply computes the sum ofrdiandrsi, whereasstruct_sumfirst has to unpack the operands into separate registers, since they both start inrdi.Negative Cost
structWhich procudes: (clang trunk
-O2)Note: GCC doesn't find this optimization for some reason.
In this case, it's better for both members to be packed into
rdi, because performing& 1with either one of them can be parallelized this way.Also see: C++ Weekly - Ep 119 - Negative Cost Structs (C++ video, but equally applies to C due to similar ABI).