为什么 likely 和 unlikely 宏对 ARM 汇编代码没有任何影响?
Why doesn't likely and unlikely macros have any effect on ARM assembly code?
我从 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
在原来的 link 中,他们已经针对 X86 对其进行了测试,如果将 likely
(在上面代码中的 if 条件中)替换为 unlikely
,则汇编输出会有所不同,它显示了编译器为分支预测执行的优化。
但是当我为 ARM (arm-gcc -O2) 编译上面的代码时,我没有看到汇编代码有任何区别。以下是两种情况下 ARM 程序集的输出 - likely
和 unlikely
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 "%d2[=11=]0"
为什么编译器不针对 ARM 的分支预测进行优化?
正如@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();
}
将 likely
更改为 unlikely
会切换 if
和 else
分支的顺序,对于 ARM 和 x86:https://godbolt.org/z/UDzvf0。如果这真的有所不同,可能取决于您 运行 使用的硬件,您是否第一次调用该函数(否则, CPU-internal 分支预测可能比指令顺序具有更大的影响), 可能还有很多其他的东西。
我从 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
.
在原来的 link 中,他们已经针对 X86 对其进行了测试,如果将 likely
(在上面代码中的 if 条件中)替换为 unlikely
,则汇编输出会有所不同,它显示了编译器为分支预测执行的优化。
但是当我为 ARM (arm-gcc -O2) 编译上面的代码时,我没有看到汇编代码有任何区别。以下是两种情况下 ARM 程序集的输出 - likely
和 unlikely
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 "%d2[=11=]0"
为什么编译器不针对 ARM 的分支预测进行优化?
正如@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();
}
将 likely
更改为 unlikely
会切换 if
和 else
分支的顺序,对于 ARM 和 x86:https://godbolt.org/z/UDzvf0。如果这真的有所不同,可能取决于您 运行 使用的硬件,您是否第一次调用该函数(否则, CPU-internal 分支预测可能比指令顺序具有更大的影响), 可能还有很多其他的东西。