GCCの最適化
id:isshiki:20060822:p1 より触発されてやってみる。
"gcc -S"ではなく、shinichiro.hさんのrelocation @amd64で覚えた"objdump -Sr"を使ってみました。等幅フォントで見てね。
"gcc-3.3.6 -O2", "gcc-3.3.6 -O3", "gcc-3.4.6 -O2", "gcc-3.4.6 -O3"の結果は、多少アドレスの違いはあるものの本質的に一緒。
int loop_function_inc(void) { 8048450: 55 push %ebp 8048451: b8 db 41 0f 00 mov $0xf41db,%eax 8048456: 89 e5 mov %esp,%ebp 8048458: 90 nop 8048459: 8d b4 26 00 00 00 00 lea 0x0(%esi),%esi 8048460: 48 dec %eax 8048461: 79 fd jns 8048460 <_Z17loop_function_incv+0x10> int i, ret = 0; for( i = loop_min; i < loop_max; i++){ ret++; } return ret; } 8048463: 5d pop %ebp 8048464: b8 dc 41 0f 00 mov $0xf41dc,%eax 8048469: c3 ret 804846a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi int loop_function_dec(void) { 8048470: 55 push %ebp int i, ret = 0; for( i = loop_max; i > loop_min; i--){ 8048471: b8 40 42 0f 00 mov $0xf4240,%eax 8048476: 89 e5 mov %esp,%ebp 8048478: 90 nop 8048479: 8d b4 26 00 00 00 00 lea 0x0(%esi),%esi 8048480: 48 dec %eax 8048481: 83 f8 64 cmp $0x64,%eax 8048484: 7f fa jg 8048480 <_Z17loop_function_decv+0x10> ret++; } return ret; } 8048486: 5d pop %ebp 8048487: b8 dc 41 0f 00 mov $0xf41dc,%eax 804848c: c3 ret 804848d: 90 nop 804848e: 89 f6 mov %esi,%esi
"gcc-4.0.3 -O2", "gcc-4.0.3 -O3"ではなんか微妙に退化しているように見える。
int loop_function_inc(void) 8048440: 55 push %ebp 8048441: 31 c0 xor %eax,%eax 8048443: 89 e5 mov %esp,%ebp 8048445: 8d 74 26 00 lea 0x0(%esi),%esi 8048449: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi { int i, ret = 0; for( i = loop_min; i < loop_max; i++){ ret++; 8048450: 40 inc %eax 8048451: 3d dc 41 0f 00 cmp $0xf41dc,%eax 8048456: 75 f8 jne 8048450 <_Z17loop_function_incv+0x10> } return ret; } 8048458: 5d pop %ebp 8048459: c3 ret 804845a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi int loop_function_dec(void) 8048460: 55 push %ebp 8048461: 31 c0 xor %eax,%eax 8048463: 89 e5 mov %esp,%ebp 8048465: 8d 74 26 00 lea 0x0(%esi),%esi 8048469: 8d bc 27 00 00 00 00 lea 0x0(%edi),%edi { int i, ret = 0; for( i = loop_max; i > loop_min; i--){ ret++; 8048470: 40 inc %eax 8048471: 3d dc 41 0f 00 cmp $0xf41dc,%eax 8048476: 75 f8 jne 8048470 <_Z17loop_function_decv+0x10> } return ret; } 8048478: 5d pop %ebp 8048479: c3 ret 804847a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
で、真打のgcc4.1.1ではやっとこさこっちの望んだ回答を得られる。
int loop_function_inc(void) 8048440: 55 push %ebp { int i, ret = 0; for( i = loop_min; i < loop_max; i++){ ret++; } return ret; } 8048441: b8 dc 41 0f 00 mov $0xf41dc,%eax 8048446: 89 e5 mov %esp,%ebp 8048448: 5d pop %ebp 8048449: c3 ret 804844a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi 08048450 <_Z17loop_function_decv>: int loop_function_dec(void) 8048450: 55 push %ebp { int i, ret = 0; for( i = loop_max; i > loop_min; i--){ ret++; } return ret; } 8048451: b8 dc 41 0f 00 mov $0xf41dc,%eax 8048456: 89 e5 mov %esp,%ebp 8048458: 5d pop %ebp 8048459: c3 ret 804845a: 8d b6 00 00 00 00 lea 0x0(%esi),%esi
ということでgcc-4.1.1万歳。
ただし、どのバージョンでも、"-O3"を指定するとmain関数の中にそれぞれの関数の戻り値が埋め込まれて、この関数達は呼ばれなくなり、何の意味もない最適化になっちゃうわけですけど。