gcc最適化オプション学習(-fomit-frame-pointer)

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

Leave a Reply

Your email address will not be published. Required fields are marked *

CAPTCHA