possible(x)和__builtin_expect((x),1)

时间:2014-06-19 07:48:54

标签: c optimization macros code-generation built-in

我知道内核非常使用likelyunlikely宏。宏的文档位于Built-in Function: long __builtin_expect (long exp, long c)。但他们并没有真正讨论细节。

编译器如何处理likely(x)__builtin_expect((x),1)

是由代码生成器还是优化器处理的?

是否取决于优化级别?

生成代码的示例是什么?

1 个答案:

答案 0 :(得分:9)

我刚刚在gcc上测试了一个简单的例子。

对于x86,这似乎由优化器处理并依赖于优化级别。虽然我猜这里的正确答案是"但这取决于编译器"。

生成的代码取决于CPU。有些cpus(sparc64立刻出现在我的脑海中,但我确定还有其他的)在条件分支指令上有标志告诉CPU如何预测它,因此编译器会生成"预测true / predict false&# 34;说明取决于编译器中的内置规则和代码中的提示(如__builtin_expect)。

英特尔在此处记录了他们的行为:https://software.intel.com/en-us/articles/branch-and-loop-reorganization-to-prevent-mispredicts。简而言之,英特尔CPU的行为是,如果CPU没有关于分支的先前信息,它将预测前向分支不太可能被采用,而可能采取向后分支(考虑循环与错误处理)。 p>

这是一些示例代码:

int bar(int);
int
foo(int x)
{
    if (__builtin_expect(x>10, PREDICTION))
        return bar(10);
    return 42;
}

编译(我使用omit-frame-pointer使输出更具可读性,但我仍在下面清理它):

$ cc -S -fomit-frame-pointer -O0 -DPREDICTION=0 -o 00.s foo.c
$ cc -S -fomit-frame-pointer -O0 -DPREDICTION=1 -o 01.s foo.c
$ cc -S -fomit-frame-pointer -O2 -DPREDICTION=0 -o 20.s foo.c
$ cc -S -fomit-frame-pointer -O2 -DPREDICTION=1 -o 21.s foo.c

00.s和01.s之间没有区别,因此这表明这取决于优化(至少对于gcc)。

这是(已清理)生成的代码为20.s:

foo:
    cmpl    $10, %edi
    jg  .L2
    movl    $42, %eax
    ret
.L2:
    movl    $10, %edi
    jmp bar

这是21.s:

foo:
    cmpl    $10, %edi
    jle .L6
    movl    $10, %edi
    jmp bar
.L6:
    movl    $42, %eax
    ret

正如预期的那样,编译器会重新安排代码,以便我们不希望采用的分支在前向分支中完成。