ADD 1真的比INC快吗? x86
我已经阅读了各种优化指南,声称ADD 1比在x86中使用INC更快。 这是真的吗?
在一些微架构上,对于一些指令stream, INC
会产生“部分标志更新失速”(因为它更新了一些标志,同时保留了其他标志)。 ADD
设置所有标志的值,所以不会冒这样的失速。
ADD
并不总是比INC
快,但几乎总是至less一样快(在某些较旧的微架构上有一些angular落的情况,但它们非常罕见),有时甚至更快。
有关更多详细信息,请参阅英特尔优化参考手册或Agner Fog的微架构笔记 。
虽然这不是一个确定的答案。 写这个C文件:
=== 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
注意生成的汇编代码。 相关的clang输出:
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
这certificate了clang和gcc的作者都认为INC
是现代架构中ADD reg, 1
的更好select。
这对你的问题意味着什么? 那么,我会相信他们对你读过的指南的判断,并得出结论: INC
和ADD
一样快,并且由于较短的寄存器编码而节省了一个字节,所以它更可取。 编译器作者只是人,所以他们可能是错的,但不太可能。 🙂
一些更多的实验表明,如果你不使用-march=native
选项,那么gcc将使用add ebx, 1
而不是add ebx, 1
。 铿锵,总是喜欢最好的公司。 我的结论是,当你在2012年问这个问题时, ADD
有时候是可取的,但现在在2016年,你应该总是和INC
一起去。
在80年代或90年代,简单的指令执行时间主要取决于指令中的组件数量:add ax,1包含一个更多的可解码单位(立即数),相比于inc ax或者增加ax,bx。 因此80286花了一个时钟周期来解码指令。
那么就有这个时代,当时英特尔特别是以CISC型指令为代价来优化大多数RISC型指令。 (例如添加ax,[mem];添加[mem],ax)。 今天或至less明天,这些都是便宜的…复杂的分支序列将被解决在30单位pipe道,自动寄存器重命名。
所以,现在我们更有可能在这个时代,在这个时代, inc eax
是CISC ,也叫坏add eax,1
是RISC ,这是好的。 但是这些事情可以在一夜之间改变。