I've lately encountered a lot of functions where gcc generates really bad code on x86. They all fit a pattern of:
if (some_condition) { /* do something really simple and return */ } else { /* something complex that needs lots of registers */ } Think of simple case as something so small that half or more of the work is spent pushing and popping registers that won't be modified at all. If I were writing the asm by hand, I would save and restore the saved-across-calls registers inside the complex case, and avoid touching the stack pointer at all in the simple case.
Is there any way to get gcc to be a little bit smarter and do this itself? Preferably with command line options rather than ugly hacks in the source...
Edit: To make it concrete, here's something very close to some of the functions I'm dealing with:
if (buf->pos < buf->end) { return *buf->pos++; } else { /* fill buffer */ } and another one:
if (!initialized) { /* complex initialization procedure */ } return &initialized_object; and another:
if (mutex->type == SIMPLE) { return atomic_swap(&mutex->lock, 1); } else { /* deal with ownership, etc. */ } Edit 2: I should have mentioned to begin with: these functions cannot be inlined. They have external linkage and they're library code. Allowing them to be inlined in the application would result in all kinds of problems.
printf("hello, world\n");to the empty blocks... Seriously it doesn't matter much what's there. If it makes one or more function calls, you'll incur stack alignment prologue, and if it uses a non-trivial amount of registers, you'll incur saving/restoring one or more of ebx/esi/edi/ebp.__builtin_expectand it makes no difference.