The following code:
struct Double2 {
double a;
double b;
};
struct Double3 {
double a;
double b;
double c;
};
double double2(struct Double2 x) {
return x.a + x.b;
}
double double3(struct Double3 x) {
return x.a + x.b + x.c;
}
double double_args(double a, double b, double c) {
return a + b + c;
}
compiles to
double2:
addsd xmm0, xmm1
ret
double3:
movsd xmm0, QWORD PTR [rsp+8]
addsd xmm0, QWORD PTR [rsp+16]
addsd xmm0, QWORD PTR [rsp+24]
ret
double_args:
addsd xmm0, xmm1
addsd xmm0, xmm2
ret
on Linux, x86-64 with GCC 9.2 with -O3 (Godbolt link)
Why is a struct of two doubles (Double2) passed via the registers xmm0 and xmm1, but a struct of three doubles (Double3) is passed via the stack? double_args() demonstrates that the compiler is at least capable of passing three doubles via registers.
Is this specified as part of the C calling convention? What is the relevant rule?