Как оптимизировать дефолтную if-ветку

У меня есть следующий фрагмент кода. Учитывая, как вызывается foo, какие аргументы компилятора могут быть заданы GCC и Clang для оптимизации оператора if, как это делает icc?

Код:

#include <cstdlib>

int foo(int i, bool b = false)
{
if (b) ++i;
return ++i;
}

int boo(int i)
{
return ++i;
}

static const bool global_b = false;
int goo(int i, bool b = global_b)
{
if (b) ++i;
return ++i;
}

int main(int argc, char* argv[])
{
int i = atoi(argv[1]);
return 2 * foo(i) + 3 * boo(i) + 7 * goo(i);
}

GCC 4.9 -O2 разборка:

foo(int, bool):
cmp   sil, 1
sbb   edi, -1
lea   eax, [rdi+1]
ret

goo(int, bool):
cmp   sil, 1
sbb   edi, -1
lea   eax, [rdi+1]
ret

boo(int):
lea   eax, [rdi+1]
ret

Clang 3.4 -O2 разборка:

foo(int, bool):
movzbl %sil, %eax
leal   1(%rdi,%rax), %eax
ret
goo(int, bool):
movzbl %sil, %eax
leal   1(%rdi,%rax), %eax
ret
boo(int):
leal  1(%rdi), %eax
ret

Разборка IntelCC 13 -O2:

foo(int, bool):
incl %edi
movl %edi, %eax
ret
goo(int):
incl %edi
movl %edi, %eax
ret
boo(int):
incl %edi
movl %edi, %eax
ret

Templatising Foo мы получаем следующее:

template <typename T>
T foo_t(T i, bool b = false)
{
if (b) ++i;
return ++i;
}

GCC 4.9 неявно встроен:

add eax, 1

3

Решение

Компилятор Intel не так. Без опции как у gcc -fwhole-program (который автоматически помечает все функции, кроме main как staticт. е. локально для этого модуля перевода), мы не знаем, foo вызывается из другого модуля перевода, поэтому компилятор не может предполагать, что он всегда вызывается со вторым аргументом, равным false,

4

Другие решения

Есть встроенный спецификатор, а также какой смысл увеличивать локальную переменную, которая была передана по значению? Вот оптимизированная версия:

#include <cstdlib>

inline int foo(int i, bool b = false)
{
// i is passed by value, no point incrementing it
//if (b) ++i;
//return ++i;
return (b)? i+2 : i+1;
}

inline int boo(int i)
{
// i is passed by value, no point incrementing it
return i+1;//++i;
}

static const bool global_b = false;
inline int goo(int i, bool b = global_b)
{
// i is passed by value, no point incrementing it
//if (b) ++i;
//return ++i;
return (b)? i+2 : i+1;
}

int main(int argc, char* argv[])
{
int i = atoi(argv[1]);
return 2 * foo(i) + 3 * boo(i) + 7 * goo(i);
}
1

Попробуйте переписать foo тело как return i+1+b;,

0

Как было упомянуто -fwhole-program это ключ к успеху.

Кроме того, вы можете определить вашу функцию как статическую (inline тоже будет работать):

static int foo(int i, bool b = false)
{
if (b) ++i;
return ++i;
}

это будет генерировать только:

add eax, 1
0

ОП рассказывает только часть истории :).

gcc -O2 фактически включает в себя все вызовы функций и main выглядит так:

main:
subq    $8, %rsp
movq    8(%rsi), %rdi
movl    $10, %edx
xorl    %esi, %esi
call    strtol
addl    $1, %eax
addq    $8, %rsp
leal    0(,%rax,8), %edx
leal    (%rdx,%rax,4), %eax
ret
0
По вопросам рекламы [email protected]