为什么宏不可能和不太可能对ARM汇编代码产生任何影响?

时间:2019-06-01 06:18:54

标签: c gcc linux-kernel arm kernel

我从https://kernelnewbies.org/FAQ/LikelyUnlikely

#include <stdio.h>
#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)

int main(char *argv[], int argc)
{
   int a;

   /* Get the value from somewhere GCC can't optimize */
   a = atoi (argv[1]);

   if (likely (a == 2))
      a++;
   else
      a--;

   printf ("%d\n", a);

   return 0;
}

并使用arm gcc 8.2 compiler对其进行https://godbolt.org/z/IC0aif编译。

在原始链接中,他们已经对其进行了X86测试,如果将likely(在上述代码中的if条件下)替换为unlikely,则汇编输出是不同的,这表明分支预测的编译器。

但是,当我为ARM编译以上代码(arm-gcc -O2)时,汇编代码没有任何区别。以下是likelyunlikely

两种情况下ARM汇编的输出。
main:
        push    {r4, lr}
        ldr     r0, [r0, #4]
        bl      atoi
        cmp     r0, #2
        subne   r1, r0, #1
        moveq   r1, #3
        ldr     r0, .L6
        bl      printf
        mov     r0, #0
        pop     {r4, pc}
.L6:
        .word   .LC0
.LC0:
        .ascii  "%d\012\000"

在ARM的情况下,编译器为什么不针对分支预测进行优化?

1 个答案:

答案 0 :(得分:1)

正如@rici所说,您的代码非常简单,可以通过条件指令来实现。您可以看到不同的地方,例如,如果您调用在其他编译单元中实现的函数:

#define likely(x)    __builtin_expect(!!(x), 1)
#define unlikely(x)  __builtin_expect(!!(x), 0)

// only forward declarations:
void foo();
void bar();

int main(char *argv[], int argc)
{
   if (likely (argc == 2))
      foo();
   else
      bar();
}

对于ARM和x86,将likely更改为unlikely会切换ifelse分支的顺序:https://godbolt.org/z/UDzvf0。如果这确实有所不同,则可能取决于您所运行的硬件,是否是首次调用该函数(否则,CPU内部分支预测的影响可能大于指令的顺序),并且可能还有很多其他影响。东西。