最適化オプションできれば、全部覚えたいのですが、アセンブラのコード差分がでないと、どうしてもどのようなオプションなのか理解が進みません。
そこで、アセンブラコードに差分がでるものから先にオプションを覚えておくことにしました。
-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がなくなったってことですね。


コメント