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は にあるのでrdi、 に格納moo*384されます。eax

于 2013-05-02T13:50:34.033 に答える
4

これは、x86 コアの標準的な最適化トリックです。アドレスを生成するプロセッサのサブセクションである AGU (アドレス生成ユニット) は、単純な演算が可能です。これは本格的な ALU ではありませんが、インデックス付きおよびスケーリング済みのアドレスを計算するのに十分なトランジスタを備えています。加算とシフト。LEA、Load Effective Address 命令は、AGU 内のロジックを呼び出して単純な式を計算させる方法です。

ここでの最適化の機会は、AGU が ALU から独立して動作することです。したがって、2 つの命令を同時に実行するスーパースカラー実行を実現できます。

これはコード スニペットでは実際には目に見えて発生しませんが、ALU を必要とする表示された命令の前に計算が行われている場合に発生する可能性があります。これは、より単純な CPU コア、486、および Pentium ヴィンテージでのみ実際に成果を上げたトリックでした。最新のプロセッサには複数の ALU があるため、このトリックはもう必要ありません。

于 2013-05-02T14:00:51.593 に答える