我正在摆弄gcc的优化选项,发现这些行:
int bla(int moo) {
return moo * 384;
}
被翻译成:
0: 8d 04 7f lea (%rdi,%rdi,2),%eax
3: c1 e0 07 shl $0x7,%eax
6: c3 retq
我理解移位代表乘以2 ^ 7。并且第一行必须乘以3。
所以我对“lea”系列完全感到困惑。是不是应该加载一个地址?
答案 0 :(得分:6)
lea (%ebx, %esi, 2), %edi
只会计算ebx + esi*2
并将结果存储在edi
中。
即使lea
旨在计算并存储有效地址,它也可以并且通常用作优化技巧来执行某些事情的计算那不是内存地址。
lea (%rdi,%rdi,2),%eax
shl $0x7,%eax
相当于:
eax = rdi + rdi*2;
eax = eax * 128;
由于moo
位于rdi
,因此会将moo*384
存储在eax
答案 1 :(得分:4)
这是x86核心的标准优化技巧。 AGU,地址生成单元,生成地址的处理器的子部分,能够进行简单的算术运算。它不是一个完整的ALU,但有足够的晶体管来计算索引和缩放的地址。添加和转移。 LEA,Load Effective Address指令是一种调用AGU中的逻辑并使其计算简单表达式的方法。
这里的优化机会是AGU独立于ALU运行。因此,您可以获得超标量执行,同时执行两条指令。
实际上并没有在您的代码段中明显发生,但如果在显示需要ALU的指令之前进行了计算,则可能发生。这是一个诀窍,只是在更简单的CPU核心,486和奔腾复古上真正得到了回报。现代处理器有多个ALU,所以不再需要这个技巧了。