如何优化默认的if-branch

时间:2014-08-21 06:17:10

标签: c++ gcc optimization icc gcc4.9

我有以下一点代码。鉴于如何调用foo,可以给GCC和Clang提供哪些编译器参数来优化像icc那样的if语句呢?

代码:

#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

5 个答案:

答案 0 :(得分:4)

英特尔的编译器错了。如果没有像gcc -fwhole-program这样的选项(它会自动将所有功能标记为main而不是static,即此翻译单元的本地功能),我们就不知道{是{从另一个翻译单元调用{1}},因此编译器不能假定它总是使用等于foo的第二个参数调用。

答案 1 :(得分:1)

是否具有内联限定符,以及递增已通过值传递的局部变量的重点是什么?这是一个优化版本:

#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);
}

答案 2 :(得分:0)

尝试将foo正文重写为return i+1+b;

答案 3 :(得分:0)

如前所述,-fwhole-program是成功的关键。

此外,您可以将函数定义为静态(内联也可以):

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

这将只生成:

add eax, 1

答案 4 :(得分:0)

OP只讲述故事的一部分:)。

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