我阅读了各种优化指南,声称在x86中使用ADD 1比使用INC更快。这是否真的正确?
我阅读了各种优化指南,声称在x86中使用ADD 1比使用INC更快。这是否真的正确?
add
。现在 P4 已经几乎被淘汰,大多数情况下人们更喜欢使用 inc
,因为它更短,并且和 add
一样快。如果你想避免修改进位标志,则可以使用 lea reg, [reg+1]
,这样就不会修改 任何 标志,避免了可怕的部分标志延迟。或者,如果可能的话,尽量避免在标志生成器和标志消费器之间进行递增。 AMD K8 到 Steamroller,以及 Intel P6 / Sandybridge 家族都会单独跟踪不同标志位的标志依赖性。例如 CF 由自己跟踪,以避免像 inc
这样的错误依赖。 - Peter Cordescmovbe
作为2个单独的输入读取。大多数cmov指令都是1个uop,但那些需要EFLAGS的两个部分的仍然是现代英特尔上的2个uops。(请参见@BeeOnRope在什么是Partial Flag Stall?上的回答)。但这意味着inc
/ dec
即使在ADC循环中也是完全有效的;没有标志合并,因此lea reg,[reg + 1]
没有优势。 - Peter Cordes=== inc.c ===
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int n = 0; n < 1000; n++) {
printf("%d\n", n);
}
return 0;
}
然后运行:
clang -march=native -masm=intel -O3 -S -o inc.clang.s inc.c
gcc -march=native -masm=intel -O3 -S -o inc.gcc.s inc.c
mov esi, ebx
call printf
inc ebx
cmp ebx, 1000
jne .LBB0_1
相关的gcc输出:
mov edi, 1
inc ebx
call __printf_chk
cmp ebx, 1000
jne .L2
INC
比ADD reg, 1
更好。那么对于您的问题,我会相信他们的判断,认为INC
与ADD
一样快,并且由于较短的寄存器编码而节省了一个字节,使其更可取。编译器作者只是人,所以他们可能会错,但这不太可能。 :)-march = native
选项,则gcc将使用add ebx,1
,而Clang则始终喜欢inc最好。我的结论是,当您在2012年提出问题时,ADD
有时更可取,但是现在在2016年,您应该始终选择INC
。,在
-Os中使用
inc ebx`。 - r00sterinc
而不是add
,您需要添加-march=native
。 - Björn Lindqvist