x86 inc与add指令的相对性能

时间:2011-05-13 14:22:08

标签: performance optimization assembly x86

快速提问,事先假设

mov eax, 0

更有效率?

inc eax
inc eax

add eax, 2

另外,如果两个inc更快,编译器(比方说,GCC)通常(即没有积极的优化标志)会优化var += 2吗?

谢谢你的时间!

PS:不要费心回答“不要过早优化”,这仅仅是学术兴趣。

4 个答案:

答案 0 :(得分:17)

同一寄存器上的两条inc指令(或更一般地说,两条读 - 修改 - 写指令)总是具有至少两个周期的依赖链。这假设一个inc的一个时钟延迟,这是自486以来的情况。这意味着如果周围的指令不能与两个inc指令交错以隐藏那些延迟,则代码将执行得更慢。

但是没有编译器会发出您建议的指令序列(mov eax,0将被xor eax,eax替换,请参阅What is the purpose of XORing a register with itself?

mov eax,0
inc eax
inc eax

将优化

mov eax,2

答案 1 :(得分:12)

如果您想知道x86指令的原始性能统计信息,请参阅Dr Agner Fogs listings(准确地说是第4卷)。至于关于编译器的部分,那依赖于编译器的代码生成器,而不是你应该依赖的东西。

旁注:我觉得有趣/具有讽刺意味的是,在有关效果的问题中,您使用MOV EAX,0将寄存器归零而不是XOR EAX,EAX:P(如果MOV EAX,0是事先完成,最快的变体是删除inc并添加'和MOV EAX,2)。

答案 2 :(得分:2)

出于所有目的,它可能无关紧要。但请注意 inc 使用较少的字节。

请考虑以下代码:

int x = 0;
x += 2;

不使用任何优化标记, GCC 将此代码编译为:

80483ed:       c7 44 24 1c 00 00 00    movl   $0x0,0x1c(%esp)
80483f4:       00 
80483f5:       83 44 24 1c 02          addl   $0x2,0x1c(%esp)

使用-O1-O2,它变为:

c7 44 24 08 02 00 00    movl   $0x2,0x8(%esp)

好笑,不是吗?

答案 3 :(得分:2)

从英特尔手册中可以找到here,看起来ADD / SUB指令在一个特定架构上的周期便宜了半个周期。但请记住,英特尔为其(最近的)处理器使用了无序执行模型。这主要意味着,在处理器必须等待数据进入的任何地方都会出现性能瓶颈(例如,在L1 / L2 / L3 / RAM数据获取期间,它已经没有事情要做)。所以,如果你是剖析器告诉你INC可能是问题;从形成数据吞吐量的角度看它,而不是查看原始循环计数。

Instruction              Latency1           Throughput         Execution Unit 
                                                            2 
CPUID                    0F_3H    0F_2H      0F_3H    0F_2H    0F_2H 

ADD/SUB                  1        0.5        0.5      0.5      ALU 
[...]
DEC/INC                  1        1          0.5      0.5      ALU