「最適化オプション」の編集履歴(バックアップ)一覧はこちら
「最適化オプション」(2014/10/25 (土) 00:23:44) の最新版変更点
追加された行は緑色になります。
削除された行は赤色になります。
sdccのCコンパイラの最適化はデフォルトで有効化される。
部分的にオプションを指定することで最適化を無効化したり、有効化する。
> sdcc -c -mz80 [optimizer option] source.c
基本的な最適化オプションは以下のとおり。
|option|内容|
|--nogcse|コード全体でsubexpressionを除去しない。&br()これはCコード上に現われる部分式の共通部分について、最適化コードが短縮化することを避ける。&br()対象はループなどに限らない。詳細は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
前者ではメモリーに変数が保存され読み書きされているが、後者はレジスタに定数化されている。
型のキャストは、前者はきちんとコードが実行されるが、後者は最適化される段階で型変換がコンパイラ処理により行なわれている。
また後者は全体としてソースのサイズも短い。
sdccのCコンパイラの最適化はデフォルトで有効化される。
部分的にオプションを指定することで最適化を無効化したり、有効化する。
> sdcc -c -mz80 [optimizer option] source.c
基本的な最適化オプションは以下のとおり。
|option|内容|
|--nogcse|コード全体でsubexpressionを除去しない。&br()これはCコード上に現われる部分式の共通部分について、最適化コードが短縮化することを避ける。&br()対象はループなどに限らない。詳細は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はビルド時に参照されている関数やライブラリのみが選択的にリンクされるため
実行形式やバイナリの肥大化はおこらない。