7

GCC コンパイラ

$ gcc --version
gcc (GCC) 4.8.2
...

inc次の C プログラムのように、実際に役立つアセンブリ命令を生成しません。

int main(int argc, char **argv)
{
    int sum = 0;
    int i;
    for(i = 0; i < 1000000000L; i++)                     <---- that "i++"
        sum += i;
    return sum;
}

代わりに、add命令を生成します。

0000000000000000 <main>:
   0:   31 d2                   xor    %edx,%edx
   2:   31 c0                   xor    %eax,%eax
   4:   0f 1f 40 00             nopl   0x0(%rax)
   8:   01 d0                   add    %edx,%eax
   a:   83 c2 01                add    $0x1,%edx         <---- HERE
   d:   81 fa 00 ca 9a 3b       cmp    $0x3b9aca00,%edx
  13:   75 f3                   jne    8 <main+0x8>
  15:   f3 c3                   repz retq 

なぜこれを行うのですか?

編集:私はgcc -O2これをコンパイルしていました。gcc -Os実際にinc命令を生成します。incスペースの最適化よりも速度の最適化を使用していませんか?

4

2 に答える 2

12

で試してみてください-march=<your machine>。結果は異なる場合があります。

ただし、add $1, %reg必ずしも悪い選択ではないことに注意してください。incdecのエンコーディングは小さいので魅力的ですが、フラグを部分的にしか更新しないため、誤った依存関係の問題が発生するという問題があります。インテルの最適化マニュアルには、次のコメントが含まれています (私の強調):

INC および DEC 命令は、フラグ レジスタ内のビットのサブセットのみを変更します。これにより、フラグ レジスタの以前のすべての書き込みへの依存が作成されます。これは、これらの命令がクリティカル パス上にある場合に特に問題になります。これらの命令は、他の多くの命令が依存するロードのアドレスを変更するために使用されるためです。アセンブリ/コンパイラ コーディング ルール 33. (M の影響、H の一般性) INC および DEC 命令は ADD または SUB 命令に置き換える必要があります。フラグを設定します。

于 2013-11-10T13:44:33.693 に答える
4

使用している (または使用していない) 正確な最適化設定に依存する場合があります。GCC は、時間または空間を最適化するように指示できます (ただし、空間を最適化することは、実行時間を最適化する効果的な方法である場合もあります!)

専門的な作業に使用できる指示があるからといって、それが必ずしも最も効率的に使用できるとは限りません。

古い x86 命令の一部は、実際にはハードウェアではなくマイクロコードで実装されています。これは、ほとんど使用されず、ハードウェアで実装する価値がないためです。ただし、これにより速度が低下する可能性があります。inc がそのような命令かどうかはわかりません。

また、コードを実行する x86 プロセッサ モデルを GCC に伝えないと、一般的なものを推測する必要があります。

于 2013-11-10T13:22:38.013 に答える