第16回 GCC2.95から追加変更のあったオプションの補足と検証(その4)

岸 哲夫

 今回は本連載第14回(本誌2004年2月号に掲載)に続いて,GCC2.95から追加変更のあったオプションの補足と検証を行います.今回は時に「最適化オプション」について扱います. (筆者)

space

-falign-functions

 関数の境界そろえを行います.-falign-functions=32と指定すると関数を32バイト境界に配置します.-falign-functionsを指定するとマシンに依存するデフォルト値が設定されます.

 PowerPCのG5では,ホット・ループ,分岐,または分岐ターゲットを32バイト境界にそろえることが推奨されています.

 ソースと生成されたコードをリスト1リスト4に示します.

 32バイトで境界そろえを行った場合は,生成されたアセンブラ・ソースに“.p2align 5,,31”という命令文が入ります.これは「2の5乗境界でそろえるが,31バイト以上のNOP命令で埋めなければならないなら境界そろえを行わない」という意味です.

 64バイトで境界そろえを行っている場合,“.p2align 6,,63”という命令文が定義されています.境界そろえを行わない場合には,その命令は定義されていません(リスト5).

 なお,-falign-functionsだけ指定した場合,i686環境下では16ビット境界にそろえられます.この場合,“.p2align 4,,15”という命令文が定義されています.

 次に示すように-falign-xxxxというオプションがいくつかありますが,基本はこれと同じです.

境界に合わせてループのアラインメントを保証する

  -falign-loops

  -falign-loops=n

境界に合わせてラベルを配置

  -falign-labels

  -falign-labels=n

境界に合わせてジャンプ命令を配置

  -falign-jumps

  -falign-jumps=n

-fbranch-probabilities

 詳細は,まだ触れていないデバッグ・オプションの項で説明しますが,-fprofile-arcsというデバッグ用のオプションがあります.そのオプションを指定すると,実行時にプログラム・コードに存在する分岐のどちらを通るかを記録します.その後,-fbranch-probabilitiesオプションを付加してコンパイルを行うと,あまり通らない分岐と必ず通る分岐を認識して強力な最適化を行います(リスト6リスト8).

 非常に単純な例で,適切なものではありませんが,次のような元ソースにある意味のないコードがアセンブラ・ソースからは排除されています.

  dummy++;

  dummy++;

  dummy++;

  dummy++;

  dummy = 0;

 このようなソースではなく,もっと複雑な分岐を持つソースで,実行に応じた最適化を行うことで役立つと思います.実際にはデバッグ時に役立つオプションなので,そのときにくわしく解説します.

-fdata-sections

 このオプションを付加すると,使われていない不要なグローバル・データを,共通領域ではなく.bss領域に配置します.

 出力されたアセンブラからもわかるように,オプションを付加しない場合には.comm領域に配置され,付加した場合には.bss領域に配置されます(リスト9リスト11).

-ffunction-sections

 このオプションを付加すると,使われていない関数のマッピング情報を明示的に除去します.

 オプションを付加した場合には,関数の配置情報が除去されています(リスト12リスト14).

 次のような疑似命令が使用している関数test1,test2に追加されていて,test3には追加されていません.

  .section .text.test1,"ax",@progbits

 これは,「割り当て可能で実行可能なtest1を.textに配置する」という意味です.

-fdelayed-branch

 RISCチップではCPU内部の最適化のために「遅延スロット」というしくみを持っているものがあります.簡単にいえば分岐命令の後の命令をつねに実行することで,効率を高める方式です.

 CPUが遅延スロットに対応しているならば,このオプションを付加してコンパイルすることで,RISCチップの機能を有効に使うことができます.ただし,Zaurusなどに使われているARMアーキテクチャのCPUには「遅延スロット」がありません.

-fdelete-null-pointer-checks

 このオプションを付けると,グローバル・データ・フロー分析を使用して,不要なヌル・ポインタ・チェックを特定し,これを削除します.最適化オプションの-O2,-O3,-Osを付けてコンパイルすれば,このオプションがデフォルトで有効になります(リスト15リスト20).

 最適化なしのオプション-O0以外は,

  printf ("p is not NULL\n");

が不要なコードとして削除されています.

-fexpensive-optimizations

 このオプションを付けると,最適化によってコンパイル時間をかけることに見合わないような細かい最適化を行います.

 しかし,塵も積もれば…というわけで,たとえばWebブラウザのMozillaなどでは,このオプションを付けることで微妙に速くなるようです.

-ffast-math

 このオプションを指定すると,次のオプションを一度に指定したことになります.

  -fno-math-errno

  -funsafe-math-optimizations

  -fno-trapping-math

  -ffinite-math-only

  -fno-signaling-nans

 結果として浮動小数点演算の精度が変わってしまうような最適化でも行うようになります.プログラムの用途によっては精度を変えてしまうと困るかもしれません.そこで意図的に,このオプションで指定するわけです(リスト21リスト23).

 リスト21にある式中の“f1 / f2”は定数にできます.そこで計算式を変更しています.ただ,この方法では当然,精度も変わってしまいます.

 なお,最適化に際しては次のオプションを同時に付加しました.

  # gcc test212.c -S -ffast-math
               -fomit-frame-pointer -O3

*          *

 次回も,引き続き「最適化オプション」の補足を行います.


NEW記事内インデックス    連載インデックスはこちら   Interfaceのトップ
◆最適化オプション
リスト

Copyright 2004 岸 哲夫

Copyright 1997-2004 CQ Publishing Co.,Ltd.