開発にあたってのノウハウ
6. Cコンパイラのオプティマイズについて
Softune C Compilerの最適化レベル毎に実施する内容です。
最適化レベル0
最適化されません。-Oを指定しないのと等価です。
最適化レベル1
プログラムの流れを詳細に解析して最適化が行われます。
- 直後への分岐の削除
- 連続した分岐の削除
- if文外実行言のthen-elseへの吸収
if 文の then 節または、else 節のどちらか一方でのみ定義のあるデータがある場合、if 文外にそのデータの定義文があれば、その文を、定義の無い節に移動する。
また、if 文に else 節がない場合は、else 節に相当する処理単位を作り、その処理単位に文を移動する。
| [最適化前] | [最適化後] |
| A=x; | (削除) |
| if (...) { | if (...) { |
| A=y; | A=y; |
| } else { | } else { |
| B=z; | B=z; A=x; |
| } | } |
- 共通式の除去
| [最適化前] | [最適化後] |
| t1=a+b; | t1=a+b; |
| t2=a+b; | t2=t1; |
- 定数計算 (定数の畳み込み)
計算可能な定数計算をコンパイル時に行なう。 - 定数の伝播
定数が代入された変数の使用を定数で置き換える。
| [最適化前] | [最適化後] | |
| a=b; | (削除) | /*以降でaが使用されない*/ |
| =a; | =0; | /*aの参照を0で置き換える*/ |
- 非実行文の削除
if 文、while 文などの条件式の真偽判定ができる時や、無条件分岐などで、実行されない文がある時は、それらのコードを生成しない。 - ループ内不変式の移動
ループ内で値が変化しない式をループの外に移動する。 - 複写の伝播
| [最適化前] | [最適化後] | |
| a=b; | (削除) | /*以降でaが使用されない*/ |
| /*この間にa,bの定義がない*/ | ||
| =a; | =b; | /*aの参照をbで置き換える*/ |
- 死変数の除去
| [最適化前] | [最適化後] |
| a=b; | (削除) |
| /*以降でaが使用されない*/ | |
- 単純代入の除去
| [最適化前] | [最適化後] |
| a=b; | a=b; |
| b=a; | (削除) |
- 強さの縮小
2のべき乗の定数による乗算をシフト化するなど、より高速な演算に置き換える。
| [最適化前] | [最適化後] |
| a=b*2; | a=b<<2; |
- 関数のインライン展開(-x func の指定と同じ)
- switch-case のテーブル分岐化
- 命令スケジューリングの実施(-Kschedule の指定と同じ)

- 遅延分岐命令の有効活用
- LD 命令のインターロックの回避
- アセンブラレベルの命令最適化
- レジスタ割り付け
最適化レベル2
最適化レベル1 に加えて、次に示す最適化が行われます。
- ループアンローリング
ループアンローリングとは、ループ回数が検出可能であるときに、ループ回数を減らすことにより実行速度の向上をはかるものですが、オブジェクトサイズ が増加する傾向があります。したがって、オブジェクトサイズを重視する場合は、この最適化を実施すべきではありません。
(アンローリング前)
for(i=0;i<3;i++){ a[i]=0;}
(アンローリング後)
a[0]=0;
a[1]=0;
a[2]=0;
最適化レベル3
最適化レベル2 に加えて、以下の最適化が行なわれます。
- 出口が2つあるループに対するループアンローリング
- if 文による分岐があるループに対するループアンローリング
- 最適化機能の繰り返し実施
最適化機能の繰返し実施は、ループ・アンローリングを除く最適化機能を、最適化の余地がなくなるまで繰り返して実施します。翻訳時間が増加します。
最適化レベル4
最適化レベル3 に加えて、以下の最適化が行なわれます。
- 演算の評価方法の変更(-Keopt の指定と同じ)
- 標準関数呼出しの変更(-Klib の指定と同じ)
Cの標準関数(strcpy、strcmp、strlen、memcpy、memset関数)のインライン展開を行ないます。標準関数のインライン展開が実施されるため、コードサイズが大きくなる可能性があります。
