2 ms·
By "doing it better", I don't believe parent is saying to create another "better" calling convention, but instead to use no convention at all.
by Narishma 10y ago
By "doing it better", I don't believe parent is saying to create another "better" calling convention, but instead to use no convention at all.
- userbinator 10y agoExactly. What I see from the "calling convention wars" is not that "it just doesn't matter all that much", it's that there is no single optimal convention in all cases. Some functions need to use more registers than others; some arguments are used very early in the function and their values are not needed after that (prefer these in a register), while others may be used later after a bunch of computation that needs many registers (these might be better staying on the stack.) Some instructions like multiply/divide require certain registers (does your function start with a multiply or divide and is one of the arguments the multiplicand/dividend? Use AX, EAX, or EDX:EAX for that one.) The short examples in the article are illustrative of "used early and not needed afterwards" --- in cdecl/stdcall the caller writes the arguments into memory, only to have the callee immediately read them back again. Ignoring the extra memory accesses, even fastcall isn't optimal in this case --- it uses ECX and EDX when what's really needed is for one of the arguments to be in EAX since it may become the return value. In my "optimised" fastcall above, you can see I had to spend an extra mov instruction just to get the return value in the right place. It would be two instructions (cmp eax, ecx | cmovge eax, ecx) otherwise. All this useless data movement, for what? Just to conform to some arbitrary convention. These may be small things, but they can add up.