最適化オプション

※上記の広告は60日以上更新のないWIKIに表示されています。更新することで広告が下部へ移動します。

sdccのCコンパイラの最適化はデフォルトで有効化される。
部分的にオプションを指定することで最適化を無効化したり、有効化する。

> sdcc -c -mz80 [optimizer option] source.c

基本的な最適化オプションは以下のとおり。

option 内容
--nogcse コード全体でsubexpressionを除去しない。
これはCコード上に現われる部分式の共通部分について、最適化コードが短縮化することを避ける。
対象はループなどに限らない。詳細は8.1.1に記載がある。
--noinvariant forループ構文条件下などで不変な部分式を検出しループ外に置き定数化する最適化を行なわない。詳細は8.1.4
--noinduction 同じくforループ構文中などのループインダクション最適化を行なわない。このオプションではループ条件下の配列インデクス掛け算などを加算に置き換え変更しない。
--nojtbound switch文の時の境界条件チェックをしない。
--noloopreverse forループ構文中などのループ境界チェックをしない。
--nolabelopt アセンブラ中のラベルに対する最適化をしない。この結果アセンブラリストが読みやすくなる。
--no-xinit-opt memcpy()を用いる際にcode領域からdata領域に対して行なうなどの場合にメモリーの初期化コードを用いない。
--nooverlay ローカル変数や関数の引数はRAM上に配置される際、変数の配置場所のオーバーレイなどをおこなわない。これは拡張メモリなどに関係するだろう。
--no-peep Peep hole最適化を行なわない。このpeep hole最適化は特にアセンブラ命令コードレベルのルールベースのパターンマッチングによるコードの無駄を削減するための最適化を行なう。
--peep-asm Peep hole最適化について、インラインアセンブラ部分は無効としパスする。
--peep-return Peep hole最適化による関数などのリターンコード部分を最適化する。これはデフォルト動作である。デバック時には無効である。
--no-peep-return リターンコードの最適化を行なうPeep hole最適化を無効とする。
--opt-code-speed 可能な限りコードサイズを無視して早いコード生成をおこなう。
--opt-code-size 可能な限りスピードを無視して小さなメモリサイズのコード生成をおこなう。
--fomit-frame-pointer ローカル変数が関数内で利用されていない場合に変数へのフレームポインタ処理を省略する。

そのほかdead code最適化(未使用の変数や関数の削除)やcopy code最適化(変数の値の複写の際、変数参照から定数に変更)なども可能らしい。

コンパイル時に最適化を無効化する場合は以下

>sdcc -c -mz80 --nogcse --nooverlay --no-peep --noinvariant 
--noinduction --nojtbound --noloopreverse --nolabelopt 
--no-xinit-opt source.c

特に指定しない場合は幾つかの最適化が有効となる。

>sdcc -c -mz80 source.c

特定のオプションを有効ならば↓

>sdcc -c -mz80 --opt-code-size source.c

コンパイラが作成するアセンブラをデバックする場合は最適化は全て無効化する方が良いだろう。


  • 最適化オプションの例

以下のソースを最適化有り、無しで比較する。


#include <stdio.h>

void main(void){
	int i=999;
	int j;
	int k;
	float a=123.4;

	for(k=0; k<10; k++){
	j=(int)a;
	printf("%d %d",i,j);
	}
}

最適化無しの時のコンパイルオプションは以下

>sdcc -c -mz80 --nogcse --nooverlay --no-peep --noinvariant 
--noinduction --nojtbound --noloopreverse --nolabelopt --no-xinit-opt src.c

アセンブラソースは以下
  0000                      48 _main_start::
  0000                      49 _main:
  0000 DD E5                50 	push	ix
  0002 DD 21 00 00          51 	ld	ix,#0
  0006 DD 39                52 	add	ix,sp
  0008 21 F8 FF             53 	ld	hl,#-8
  000B 39                   54 	add	hl,sp
  000C F9                   55 	ld	sp,hl
                            56 ;src.c:5: int i=999;
  000D DD 36 FE E7          57 	ld	-2 (ix),#0xE7
  0011 DD 36 FF 03          58 	ld	-1 (ix),#0x03
                            59 ;src.c:8: float a=123.4;
  0015 DD 36 F8 CD          60 	ld	-8 (ix),#0xCD
  0019 DD 36 F9 CC          61 	ld	-7 (ix),#0xCC
  001D DD 36 FA F6          62 	ld	-6 (ix),#0xF6
  0021 DD 36 FB 42          63 	ld	-5 (ix),#0x42
                            64 ;src.c:10: for(k=0; k<10; k++){
  0025 DD 36 FC 00          65 	ld	-4 (ix),#0x00
  0029 DD 36 FD 00          66 	ld	-3 (ix),#0x00
  002D                      67 00108$:
  002D                      68 00101$:
  002D DD 7E FC             69 	ld	a,-4 (ix)
  0030 D6 0A                70 	sub	a, #0x0A
  0032 DD 7E FD             71 	ld	a,-3 (ix)
  0035 DE 00                72 	sbc	a, #0x00
  0037 E2r3Cs00             73 	jp	PO, 00109$
  003A EE 80                74 	xor	a, #0x80
  003C                      75 00109$:
  003C FAr42s00             76 	jp	M,00102$
  003F C3r75s00             77 	jp	00105$
  0042                      78 00102$:
                            79 ;src.c:11: j=(int)a;
  0042 DD 6E FA             80 	ld	l,-6 (ix)
  0045 DD 66 FB             81 	ld	h,-5 (ix)
  0048 E5                   82 	push	hl
  0049 DD 6E F8             83 	ld	l,-8 (ix)
  004C DD 66 F9             84 	ld	h,-7 (ix)
  004F E5                   85 	push	hl
  0050 CDr00s00             86 	call	___fs2sint
  0053 F1                   87 	pop	af
  0054 F1                   88 	pop	af
  0055 4D                   89 	ld	c,l
  0056 44                   90 	ld	b,h
                            91 ;src.c:12: printf("%d %d",i,j);
  0057 11r7As00             92 	ld	de,#__str_0
  005A C5                   93 	push	bc
  005B DD 6E FE             94 	ld	l,-2 (ix)
  005E DD 66 FF             95 	ld	h,-1 (ix)
  0061 E5                   96 	push	hl
  0062 D5                   97 	push	de
  0063 CDr00s00             98 	call	_printf
  0066 F1                   99 	pop	af
  0067 F1                  100 	pop	af
  0068 F1                  101 	pop	af
  0069                     102 00103$:
                           103 ;src.c:10: for(k=0; k<10; k++){
  0069 DD 34 FC            104 	inc	-4 (ix)
  006C C2r72s00            105 	jp	NZ,00110$
  006F DD 34 FD            106 	inc	-3 (ix)
  0072                     107 00110$:
  0072 C3r2Ds00            108 	jp	00101$
  0075                     109 00104$:
  0075                     110 00105$:
  0075 DD F9               111 	ld	sp,ix
  0077 DD E1               112 	pop	ix
  0079 C9                  113 	ret
  007A                     114 _main_end::
  007A                     115 __str_0:
  007A 25 64 20 25 64      116 	.ascii "%d %d"
  007F 00                  117 	.db 0x00
                           118 	.area _CODE
                           119 	.area _CABS

最適化オプション有りの場合
> sdcc -c -mz80 src.c

アセンブラソース
  0000                      48 _main_start::
  0000                      49 _main:
                            50 ;src.c:10: for(k=0; k<10; k++){
  0000 11 0A 00             51 	ld	de,#0x000A
  0003                      52 00103$:
                            53 ;src.c:12: printf("%d %d",i,j);
  0003 01r1Ds00             54 	ld	bc,#__str_0
  0006 D5                   55 	push	de
  0007 21 7B 00             56 	ld	hl,#0x007B
  000A E5                   57 	push	hl
  000B 21 E7 03             58 	ld	hl,#0x03E7
  000E E5                   59 	push	hl
  000F C5                   60 	push	bc
  0010 CDr00s00             61 	call	_printf
  0013 F1                   62 	pop	af
  0014 F1                   63 	pop	af
  0015 F1                   64 	pop	af
  0016 D1                   65 	pop	de
  0017 1B                   66 	dec	de
                            67 ;src.c:10: for(k=0; k<10; k++){
  0018 7A                   68 	ld	a,d
  0019 B3                   69 	or	a,e
  001A 20 E7                70 	jr	NZ,00103$
  001C C9                   71 	ret
  001D                      72 _main_end::
  001D                      73 __str_0:
  001D 25 64 20 25 64       74 	.ascii "%d %d"
  0022 00                   75 	.db 0x00
                            76 	.area _CODE
                            77 	.area _CABS


前者ではメモリーに変数が保存され読み書きされているが、後者はレジスタに定数化されている。
型のキャストは、前者はきちんとコードが実行されるが、後者は最適化される段階で型変換がコンパイラ処理により行なわれている。
また後者は全体としてソースのサイズも短い。

MSDOSのCコンパイラは標準ライブラリ全てがリンカで結合されるためにexeのバイナリ
ファイルサイズが極端に大きくなるが、
SDCCはビルド時に参照されている関数やライブラリのみが選択的にリンクされるため
実行形式やバイナリの肥大化はおこらない。
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。