2

我正在摆弄 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”线弄糊涂了。lea 不应该加载地址吗?

4

2 回答 2

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是 in rdi,它就存储moo*384eax

于 2013-05-02T13:50:34.033 回答
4

这是 x86 内核上的标准优化技巧。AGU(地址生成单元)是处理器中生成地址的子部分,能够进行简单的算术运算。它不是一个成熟的 ALU,但有足够的晶体管来计算索引和缩放地址。添加和转移。LEA,加载有效地址指令是一种调用 AGU 中的逻辑并使其计算简单表达式的方法。

这里的优化机会是 AGU 独立于 ALU 运行。所以你可以获得超标量执行,两条指令同时执行。

这实际上并没有在您的代码片段中明显发生,但如果在显示的需要 ALU 的指令之前进行计算,则可能会发生这种情况。这是一个技巧,只有在更简单的 cpu 内核、486 和 Pentium 年份才能真正得到回报。现代处理器有多个 ALU,所以不再需要这个技巧了。

于 2013-05-02T14:00:51.593 回答