Pre*_*zer 9 optimization performance x86 assembly
快速提问,事先假设
mov eax, 0
Run Code Online (Sandbox Code Playgroud)
哪个更有效率?
inc eax
inc eax
Run Code Online (Sandbox Code Playgroud)
要么
add eax, 2
Run Code Online (Sandbox Code Playgroud)
另外,如果两个incs更快,编译器(比方说,GCC)通常(即没有积极的优化标志)是否优化var += 2呢?
谢谢你的时间!
PS:不要费心回答"不要过早优化",这仅仅是学术兴趣.
Gun*_*iez 18
inc同一寄存器上的两条指令(或更一般地说,两条读 - 修改 - 写指令)总是具有至少两个周期的依赖链.这假设一个inc的一个时钟延迟,这是自486以来的情况.这意味着如果周围的指令不能与两个inc指令交错以隐藏那些延迟,则代码将执行得更慢.
但是没有编译器会发出你提出的指令序列(mov eax,0将替换为xor eax,eax,看看寄存器与自身进行异或的目的是什么?)
mov eax,0
inc eax
inc eax
Run Code Online (Sandbox Code Playgroud)
它会被优化
mov eax,2
Run Code Online (Sandbox Code Playgroud)
Nec*_*lis 12
如果您想知道x86指令的原始性能统计数据,请参阅Agner Fogs博士列表(确切地说是第4卷).关于编译器的部分,那依赖于编译器的代码生成器,而不是你应该依赖的东西.
在旁注:我觉得有趣/具有讽刺意味的是,在关于性能的问题中,你习惯于MOV EAX,0将寄存器归零而不是XOR EAX,EAX:P(如果MOV EAX,0事先完成,最快的变体就是删除inc并添加'和' MOV EAX,2).
出于所有目的,这可能并不重要。但请考虑到inc使用较少的字节。
考虑以下代码:
int x = 0;
x += 2;
Run Code Online (Sandbox Code Playgroud)
在不使用任何优化标志的情况下,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)
Run Code Online (Sandbox Code Playgroud)
使用-O1和-O2,它变成:
c7 44 24 08 02 00 00 movl $0x2,0x8(%esp)
Run Code Online (Sandbox Code Playgroud)
很有趣,不是吗?