最適化オプションできれば、全部覚えたいのですが、アセンブラのコード差分がでないと、どうしてもどのようなオプションなのか理解が進みません。
そこで、アセンブラコードに差分がでるものから先にオプションを覚えておくことにしました。
-O2と-O3の差分を除いて、-O~は、既に確認したので、それ以外のオプションについて確認していこうと思います。(全部差分がでないかもしれませんが)
man gccから抜粋。
最適化オプション -fcaller-saves -fcse-follow-jumps -fcse-skip-blocks -fdelayed-branch -felide-constructors -fexpensive-optimizations -ffast-math -ffloat-store -fforce-addr -fforce-mem -finline-functions -fkeep-inline-functions -fmemoize-lookups -fno-default-inline -fno-defer-pop -fno-function-cse -fno-inline -fno-peephole -fomit-frame-pointer -frerun-cse-after-loop -fschedule-insns -fschedule-insns2 -fstrength-reduce -fthread-jumps -funroll-all-loops -funroll-loops -O -O2 -O3 -O0 -Os
listというファイルに、オプションを並べます。
takk@deb9:~/tmp$ cat -n list 1 -fcaller-saves 2 -fcse-follow-jumps 3 -fcse-skip-blocks 4 -fdelayed-branch 5 -felide-constructors 6 -fexpensive-optimizations 7 -ffast-math 8 -ffloat-store 9 -fforce-addr 10 -fforce-mem 11 -finline-functions 12 -fkeep-inline-functions 13 -fmemoize-lookups 14 -fno-default-inline 15 -fno-defer-pop 16 -fno-function-cse 17 -fno-inline 18 -fno-peephole 19 -fomit-frame-pointer 20 -frerun-cse-after-loop 21 -fschedule-insns 22 -fschedule-insns2 23 -fstrength-reduce 24 -fthread-jumps 25 -funroll-all-loops 26 -funroll-loops takk@deb9:~/tmp$
gccを連続実行する前に、echoをつけて確認。
takk@deb9:~/tmp$ for i in `<list`;do echo gcc -o asm$i.s -S $i t.c;done gcc -o asm-fcaller-saves.s -S -fcaller-saves t.c gcc -o asm-fcse-follow-jumps.s -S -fcse-follow-jumps t.c gcc -o asm-fcse-skip-blocks.s -S -fcse-skip-blocks t.c gcc -o asm-fdelayed-branch.s -S -fdelayed-branch t.c gcc -o asm-felide-constructors.s -S -felide-constructors t.c gcc -o asm-fexpensive-optimizations.s -S -fexpensive-optimizations t.c gcc -o asm-ffast-math.s -S -ffast-math t.c gcc -o asm-ffloat-store.s -S -ffloat-store t.c gcc -o asm-fforce-addr.s -S -fforce-addr t.c gcc -o asm-fforce-mem.s -S -fforce-mem t.c gcc -o asm-finline-functions.s -S -finline-functions t.c gcc -o asm-fkeep-inline-functions.s -S -fkeep-inline-functions t.c gcc -o asm-fmemoize-lookups.s -S -fmemoize-lookups t.c gcc -o asm-fno-default-inline.s -S -fno-default-inline t.c gcc -o asm-fno-defer-pop.s -S -fno-defer-pop t.c gcc -o asm-fno-function-cse.s -S -fno-function-cse t.c gcc -o asm-fno-inline.s -S -fno-inline t.c gcc -o asm-fno-peephole.s -S -fno-peephole t.c gcc -o asm-fomit-frame-pointer.s -S -fomit-frame-pointer t.c gcc -o asm-frerun-cse-after-loop.s -S -frerun-cse-after-loop t.c gcc -o asm-fschedule-insns.s -S -fschedule-insns t.c gcc -o asm-fschedule-insns2.s -S -fschedule-insns2 t.c gcc -o asm-fstrength-reduce.s -S -fstrength-reduce t.c gcc -o asm-fthread-jumps.s -S -fthread-jumps t.c gcc -o asm-funroll-all-loops.s -S -funroll-all-loops t.c gcc -o asm-funroll-loops.s -S -funroll-loops t.c takk@deb9:~/tmp$
takk@deb9:~/tmp$ for i in `<list`;do gcc -o asm$i.s -S $i t.c;done cc1: warning: this target machine does not have delayed branches cc1: warning: command line option ‘-felide-constructors’ is valid for C++/ObjC++ but not for C gcc: error: unrecognized command line option ‘-fforce-mem’; did you mean ‘-fforce-addr’? gcc: error: unrecognized command line option ‘-fmemoize-lookups’; did you mean -falign-loops’? takk@deb9:~/tmp$
2個のオプションでエラーになりました。私の環境のman gccの情報が古かったかもしれません。
takk@deb9:~/tmp$ wc -l list 26 list takk@deb9:~/tmp$ takk@deb9:~/tmp$ ls asm* | wc -l 24 takk@deb9:~/tmp$
では、最適化オプションなしのアセンブラとの比較をしていきます。
takk@deb9:~/tmp$ for i in asm*.s;do echo "===$i====";diff t.s $i;done ===asm-fcaller-saves.s==== ===asm-fcse-follow-jumps.s==== ===asm-fcse-skip-blocks.s==== ===asm-fdelayed-branch.s==== ===asm-felide-constructors.s==== ===asm-fexpensive-optimizations.s==== ===asm-ffast-math.s==== ===asm-ffloat-store.s==== ===asm-fforce-addr.s==== ===asm-finline-functions.s==== ===asm-fkeep-inline-functions.s==== ===asm-fno-default-inline.s==== ===asm-fno-defer-pop.s==== ===asm-fno-function-cse.s==== ===asm-fno-inline.s==== ===asm-fno-peephole.s==== ===asm-fomit-frame-pointer.s==== 8,12d7 < pushq %rbp < .cfi_def_cfa_offset 16 < .cfi_offset 6, -16 < movq %rsp, %rbp < .cfi_def_cfa_register 6 17,18d11 < popq %rbp < .cfi_def_cfa 7, 8 28,32d20 < pushq %rbp < .cfi_def_cfa_offset 16 < .cfi_offset 6, -16 < movq %rsp, %rbp < .cfi_def_cfa_register 6 34,35c22,24 < movl $10, -4(%rbp) < cmpl $10, -4(%rbp) --- > .cfi_def_cfa_offset 24 > movl $10, 12(%rsp) > cmpl $10, 12(%rsp) 44,45c33,34 < leave < .cfi_def_cfa 7, 8 --- > addq $16, %rsp > .cfi_def_cfa_offset 8 ===asm-frerun-cse-after-loop.s==== ===asm-fschedule-insns.s==== ===asm-fschedule-insns2.s==== ===asm-fstrength-reduce.s==== ===asm-fthread-jumps.s==== ===asm-funroll-all-loops.s==== ===asm-funroll-loops.s==== takk@deb9:~/tmp$
差分が出たのは、たったの一個でした。
asm-fomit-frame-pointer.s
man gccを読んでみます。
-fomit-frame-pointer フレームポインタをレジスタに格納する必要のない関数において、この 処理を 行いません。これはフレームポインタの保存、設定、復帰にか かる命令を省略 し、さらに、多くの関数でレジスタ変数として使用で きる余分なレジスタを 得ることを可能にします。ただし、このオプ ションはほとんどのマシンにおいてデバッグを不可能にします。 Vax などのいくつかのマシンでは、このフラグは効果を持ちません。な ぜならこ れらのマシンでは標準の呼び出し手順が自動的にフレームポ インタの設定を 行なってしまい、これが存在しないとしたところで何 も節約ができないからです。 マシン記述マクロ FRAME_POINTER_REQUIRED が、ターゲットマシンがこのフラグをサポー トするかどうかを制御しています。
takk@deb9:~/tmp$ cat -n asm-fomit-frame-pointer.s 1 .file "t.c" 2 .comm b,4,4 3 .text 4 .type func1, @function 5 func1: 6 .LFB0: 7 .cfi_startproc 8 movl b(%rip), %eax 9 addl $50, %eax 10 movl %eax, b(%rip) 11 nop 12 ret 13 .cfi_endproc 14 .LFE0: 15 .size func1, .-func1 16 .globl main 17 .type main, @function 18 main: 19 .LFB1: 20 .cfi_startproc 21 subq $16, %rsp 22 .cfi_def_cfa_offset 24 23 movl $10, 12(%rsp) 24 cmpl $10, 12(%rsp) 25 jne .L3 26 movl $100, b(%rip) 27 jmp .L4 28 .L3: 29 movl $200, b(%rip) 30 .L4: 31 call func1 32 movl b(%rip), %eax 33 addq $16, %rsp 34 .cfi_def_cfa_offset 8 35 ret 36 .cfi_endproc 37 .LFE1: 38 .size main, .-main 39 .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516" 40 .section .note.GNU-stack,"",@progbits takk@deb9:~/tmp$
不要なpush/popがなくなったってことですね。
コメント