这是来自《计算机系统:程序员的视角》的示例代码。
short foo(short a, short b) {
short result;
result = b;
while(b > 0) {
result *= a;
b -= a;
}
return result;
}
使用
gcc14.2
和 -O1
与 -O3
进行编译,得到以下组件 (godbolt)
O1
foo:
movl %esi, %eax
movl %esi, %ecx
testw %si, %si
jle .L1
.L3:
imull %edi, %eax
subl %edi, %ecx
testw %cx, %cx
jg .L3
.L1:
ret
O3
foo:
movl %esi, %eax
movl %esi, %edx
testw %si, %si
jle .L1
.L3:
subl %edi, %edx
imull %edi, %eax
testw %dx, %dx
jg .L3
.L1:
ret
对于
O3
,sub
位于 imul
之前 - 为什么这种重新排序有帮助?
正如您所注意到的,
subl
和imul
可以并行执行(都不依赖于另一个),但是testw
确实取决于subl
的结果(理论上,是否使用下一个imul
的结果取决于testw
)因此,您想要完成并因此尽快开始subl
,以便无论testw
是否已完成,imul
都可以开始.