Как избежать накладных расходов на пролог функции gcc?

В последнее время я встречал множество функций, в которых gcc генерирует действительно плохой код на x86. Все они соответствуют шаблону:

if (some_condition) {
    /* do something really simple and return */
} else {
    /* something complex that needs lots of registers */
}

Думайте о простом случае как о чем-то настолько маленьком, что половина или больше работы тратится на выталкивание и извлечение регистров, которые вообще не будут изменены. Если бы я писал asm вручную, я бы сохранил и восстановил регистры сохраненных между вызовами внутри сложного случая и вообще не касался бы указателя стека в простом случае.

Есть ли способ заставить gcc работать с быть немного умнее и сделать это само? Желательно с параметрами командной строки, а не с уродливыми хаками в исходном коде ...

Edit: Чтобы сделать это конкретнее, вот что-то очень похожее на некоторые функции, с которыми я имею дело:

if (buf->pos < buf->end) {
    return *buf->pos++;
} else {
    /* fill buffer */
}

и еще одна:

if (!initialized) {
    /* complex initialization procedure */
}
return &initialized_object;

и еще один:

if (mutex->type == SIMPLE) {
    return atomic_swap(&mutex->lock, 1);
} else {
    /* deal with ownership, etc. */
}

Edit 2: Я должен был упомянуть для начала: эти функции не могут быть встроены. У них есть внешняя связь, и они являются библиотечным кодом. Разрешение им быть встроенным в приложение приведет к разного рода проблемам.

12
задан R.. 29 March 2011 в 19:31
поделиться