Mindless ABI adherence
Linus Torvalds
torvalds@transmeta.com
Fri Oct 19 09:26:00 GMT 2001
In article < 871yjz8x5s.fsf@deneb.enyo.de > you write:
>"D. J. Bernstein" <djb@cr.yp.to> writes:
>
>> Similarly, even though the x86 ABI requires function arguments to be
>> passed on the stack, it's usually quite a bit faster to pass arguments
>> in registers. A small amount of work here would noticeably speed up a
>> huge number of programs.
>
>You can already do this using function attributes and/or command line
>switches. Since the x86 has so few registers, it is not clear if
>register passing is a win in all situations.
You can _not_ do it in practice with command line switches.
Why? Because that breaks horribly for precompiled object files, ie
libraries. And the only projects I know of that don't use standard
libraries are various OS kernels floating around.
Linux _does_ use function attributes, although relatively sparingly
because gcc has historically had problems with register pressure. Those
troubles seem to be behind us. Knock wood.
I think it might be a good idea to do it automatically (with a command
line switch to enable it) - you can easily do it without even having
lookahead by just doing:
- any static function is generated with the "best" calling conventions
(and those may depend on the function - so save away what they are,
so that):
- if the address of the function is taken, we set a flag that we have
to generate a "stub" function if we haven't already, and we return
the address of the stub. The stub does the standard->best conversion.
So if you have code like
static int add(int a, int b)
{
return a+b;
}
...
add(x,y);
fnptr = &add;
...
it would generate
add:
addl %edx,%eax
ret;
stub$add:
movl 4(%esp),eax
movl 8(%esp),edx
jmp add;
which is not noticeably slower even for the indirect case, and the
direct call will obviously be faster.
(Yeah, yeah, it should be inlined, but it's just an _example_).
That said, register calling doesn't always improve code _that_ much on
x86, just because the callee sometimes has to save away the arguments
anyway. But even then it tends to be smaller (stack operations in one
place instead of in all callers).
Note that this is really a generic optimization, and has nothing to do
with x86 or register passing at all. And you don't even have to limit
yourself to static functions if you teach your linker about the stub vs
non-stub issues. Which is useful on alpha for the GP optimization, and
can be very useful on just about any architecture for things like
limiting your call-clobbered registers.
For example, you can also do things like "Oh, I noticed when I generated
the code for this function that it doesn't actually clobber register XX
even though it's call-clobbered, so every caller I generate after this
can know that", and similar optimizations to the standard calling
convention ("this function does not change memory" etc).
Linus
More information about the Gcc-bugs
mailing list