2011-10-27 7 views
0

奇妙な一時的な変数を追加します:Linux上でGCC(v4.4.5、なしの最適化)とそれをGCCは、私はこのコードを作成している

#include <stdio.h> 

typedef unsigned int uint; 
uint in[2]={1,2},out[2]={3,4}; 

int main() { 

    in[0]=out[0]/10; 
} 

をコンパイルし、結果のアセンブリは次のようになります。今

0000000000400474 <main>: 
400474:  55      push rbp 
400475:  48 89 e5    mov rbp,rsp 
400478:  8b 05 ae 03 20 00  mov eax,DWORD PTR [rip+0x2003ae]  # 0082c <out> 
40047e:  89 45 fc    mov DWORD PTR [rbp-0x4],eax 
400481:  ba cd cc cc cc   mov edx,0xcccccccd 
400486:  8b 45 fc    mov eax,DWORD PTR [rbp-0x4] 
400489:  f7 e2     mul edx 
40048b:  89 d0     mov eax,edx 
40048d:  c1 e8 03    shr eax,0x3 
400490:  89 05 8e 03 20 00  mov DWORD PTR [rip+0x20038e],eax  # 600824 <in> 
400496:  c9      leave 
400497:  c3      ret 
400498:  90      nop 
400499:  90      nop 
40049a:  90      nop 
40049b:  90      nop 
40049c:  90      nop 
40049d:  90      nop 
40049e:  90      nop 
40049f:  90      nop 

問題は、このコードは5行目で何をしているのですか?

40047e:  89 45 fc    mov DWORD PTR [rbp-0x4],eax 

メモリ内のある場所に再び値[0]を保存していませんか?なぜそうなのか?私はある場所にすぐに読み書きするように言っていませんでした。

さて、この一時的な変数は、ライン#7上のアドレス400486で再度表示されます。

400486:  8b 45 fc    mov eax,DWORD PTR [rbp-0x4] 

この例では、GCCは非常に非効率的なコードを生成しているように見え、それが原因でこれらのキャッシュラインを追い出します一時的な貯蔵。確認してください、多分私が得ていない何かがあります。

+7

まあ、あなたは最適化がないと言っていました。 –

+2

もちろん非効率なコードを生成しています。あなたはそれを最適化しないように言いました。 – Dave

+1

'rbp-0x4'はスタックしていませんか?以前は 'mov rbp、rsp'を行っています。 –

答えて

5

-O0でコンパイルすると、GCCが非常に非効率なコードになります。実際には、プログラムの内部表現の基本的な翻訳です。この内部表現にはいくつかの一時変数があり、ここでのロード/ストアのペアはそのような一時的なものを通る値です。より高い最適化レベルでは、これらの無駄なロード/ストアはほとんどなくなります。 -O0であっても、最も簡単な分析が無効になっています。

+0

私はILがスタックベースのマシンでなければならないと思います。私は 'return argc;'を追加し、それを返す前にargcをスタックにコピーしました。 (私も単純な変数に入れ替えてみましたが、 '(1 << 32)* 0.8'をスタックにコピーしました)比較すると'/Od'でもMSVCコンパイラは一般的に 'mov eax、_out'を出します。 xor edx、edx'' mov ecx、10'' div ecx'' mov _in、eax'です。 (これは '/ O2'でmulを使用しています) – Neil

+1

@Neil:GCCにはいくつかの異なる中間表現があります:GIMPLE、SSA、RTL、...もちろんSSA形式は一時変数のロードを作成します。 – ninjalj

+0

私はそれを得てありがとう。私は、GCCによって生成された元のコードが、-O0であっても、レジスタ値を保存したり復元したりせずにやったことをやると思っていました。 – Nulik