gcc最適化(O2/O3)アセンブラ比較(その2)


アニメ『となりの吸血鬼さん』

神アニメなんでしょうけど、そこまで夢中になって見てません。でも、見ると癒されます。

gcc -O3オプションの続きです。
もう一度、-O3オプションの説明を読んでみます。

       -O3    さらなる最適化を行います。これは  -O2 が行う全ての最適化手段に加
              えて -finline-functions も有効にします。

-O2との差分としては、-finline-functionsのオプションがあるかないかってことですね。
インライン関数を有効にするってことでしょうか。
オプションの説明を見てみます。

       -finline-functions
              全ての単純な関数を呼び出し側に組み込んでしまいます。コンパイラは
              ヒューリスティックスを用いて、  どの関数がこの方法で組み込むに足
              りるほど単純かを決定します。

              もし、ある関数に対する全ての呼び出しを組み込むことができ、かつそ
              の関数が static と宣言されていた場合は、GCC はその関数を独立した
              アセンブラコードと しては出力をしません。

なるほど。前回は関数が単純すぎたので、引数を使って戻り値も返してくれる関数に変更してみます。

takk@deb9:~/tmp$ cat -n t.c
     1  int func1(int a)
     2  {
     3          return a + 50;
     4  }
     5
     6  int main()
     7  {
     8          int a=10;
     9          int b;
    10          if(a == 10)
    11                  b = 100;
    12          else
    13                  b = 200;
    14
    15          return func1(b);
    16  }
takk@deb9:~/tmp$

これでどうでしょうか。アセンブラを確認します。

takk@deb9:~/tmp$ gcc -o t-O2.s -S -O2 t.c
takk@deb9:~/tmp$ cat -n t-O2.s
     1          .file   "t.c"
     2          .text
     3          .p2align 4,,15
     4          .globl  func1
     5          .type   func1, @function
     6  func1:
     7  .LFB0:
     8          .cfi_startproc
     9          leal    50(%rdi), %eax
    10          ret
    11          .cfi_endproc
    12  .LFE0:
    13          .size   func1, .-func1
    14          .section        .text.startup,"ax",@progbits
    15          .p2align 4,,15
    16          .globl  main
    17          .type   main, @function
    18  main:
    19  .LFB1:
    20          .cfi_startproc
    21          movl    $150, %eax
    22          ret
    23          .cfi_endproc
    24  .LFE1:
    25          .size   main, .-main
    26          .ident  "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
    27          .section        .note.GNU-stack,"",@progbits
takk@deb9:~/tmp$

一応func1はアセンブラコード上存在してますね。
では、-O2と-O3のアセンブラコードを比較してみます。

takk@deb9:~/tmp$ gcc -o t-O3.s -S -O3 t.c
takk@deb9:~/tmp$ diff t-O2.s t-O3.s
takk@deb9:~/tmp$

-O2と-O3、変化なしです。
少し複雑だったのかもしれません。戻り値をなくして、もう少し単純な関数にしてみます。

takk@deb9:~/tmp$ cat -n t.c
     1  void func1(int* a)
     2  {
     3          *a = *a + 50;
     4  }
     5
     6  int main()
     7  {
     8          int a=10;
     9          int b;
    10          if(a == 10)
    11                  b = 100;
    12          else
    13                  b = 200;
    14
    15          func1(&b);
    16
    17          return b;
    18  }
takk@deb9:~/tmp$

比較します。

takk@deb9:~/tmp$ gcc -o t-O2.s -O2 -S t.c
takk@deb9:~/tmp$ gcc -o t-O3.s -O3 -S t.c
takk@deb9:~/tmp$ diff t-O2.s t-O3.s
takk@deb9:~/tmp$

変化なしです。

関数をもっと単純にします。

takk@deb9:~/tmp$ cat -n t.c
     1  int b;
     2  void func1(void)
     3  {
     4          b = b + 50;
     5  }
     6
     7  int main()
     8  {
     9          int a=10;
    10          if(a == 10)
    11                  b = 100;
    12          else
    13                  b = 200;
    14
    15          func1();
    16
    17          return b;
    18  }
takk@deb9:~/tmp$

比較。

takk@deb9:~/tmp$ gcc -o t-O3.s -O3 -S t.c
takk@deb9:~/tmp$ gcc -o t-O2.s -O2 -S t.c
takk@deb9:~/tmp$ diff t-O2.s t-O3.s
takk@deb9:~/tmp$

変化なしです。
おかしいですねえ。

つづく

Leave a Reply

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

CAPTCHA