独自言語 picle のコンパイラ化(その6) [PIC]
picleコンパイラ製作の続編です。
前回公開したVer0.01では main() 内で「}」 が不足した場合、ソース領域を超えて解析してしまう問題があったのでパース途中でソースエンドになった場合、エラー検出するようにしました ^^;
最適化の効果(公開版ではアセンブルリストは表示されません)
[TOP] [ 前へ ] 連載記事 [ 次へ ]
前回公開したVer0.01では main() 内で「}」 が不足した場合、ソース領域を超えて解析してしまう問題があったのでパース途中でソースエンドになった場合、エラー検出するようにしました ^^;
- コンパイルの最適化
次の最適化を盛り込みました。
対応前後のコンパイル結果比較を末尾に示します。
- (1) 直値の事前計算
数式内で直値同士の計算はコンパイル時に行うようにした。
直値計算でゼロ除算が発生した場合、コンパイル時に実行時のゼロ除算と同様なメッセージが表示される。
:{var a;a=2/(6-2*3);}
Divided by 0 err :/(6-2*3);}
:
- (2) 配列アクセスの最適化
インデックスが 10 bit 以内の場合、PIC24 には直値インデックス付きインダイレクトアドレッシングのMOV命令があるので利用するようにした。
- (3) 連続したセーブ&ロードの最適化
ローカル変数値を設定直後に参照する場合、参照コードを削除した。
但し、単純に削除すると他からのジャンプ先になっている場合、値が設定されないのでジャンプ先の場合は削除対象外とした。
下記の最適化後(右側)で次の行のアドレスが進んでいない行が削除された命令。
- (1) 直値の事前計算
- 制御構文の追加
下記の最適化の前後比較は動作確認のため意図的に最適化にヒットするように作った処理自体は意味の無いソースなので通常のソースでは効果はそれ程無いものと思っています。
反面コンパイラのサイズが増大しコンパクト性という利点を失いつつ(かつ内部ロジックが複雑化)の変更なので改悪になるかもしれません。
ということでもっと効果的な変更をした方がいいと思い直し、制御文を2つ追加しました(こちらはソース的にもわずかな追加)
- else if 文の実装
else if が無いとソースのインデントが深くなってしまうので (使い易さ/ソース増) で言えばこちらの方が改善と思う。
「else if」は1つのワード扱いなので perl の elsif 等のように一語にすべきかとも思ったが見慣れたスタイル(人にもよるけど)ということでC言語スタイルにした。
パースを簡略化しているので 「else」と「if」の間がスペース2個以上だったりするとエラーになる w
- while { } 文の実装
for 文で代用できるのでなくても良いかなぁと思っていたがやはりあった方がソースが見やすくなるので追加した。
- else if 文の実装
- ダウンロード
今回の変更版は下記リンクの記事からダウンロードできます。
「独自言語 picle compiler on PIC24FJ」
before | after |
---|---|
:l 1:# optimized code test 2: 3:func abc( x ) { 4: var ar, y; 5: 6: ar = x; 7: ar[ 5 ] = 2+3*4; 8: y = ar[ 5 ]; 9: return = y; 10:} 11: 12: 13:proc main() { 14: PrnStr_( "¥n abc = " ); 15: PrnDec_( abc( Array_ ) ); 16:} :run 8000 : MOV W15,[e5ah] 8002 : MOV W14,[e5ch] 8004 : BRA 8050h 8006 : MOV [e5ch],W14 8008 : MOV [e5ah],W15 800a : RETURN 800c : LNK #8 800e : MOV W0,[W14+0h] 8010 : CLR W0 8012 : MOV W0,[W14+2h] 8014 : MOV [W14+0h],W0 8016 : MOV W0,[W14+4h] 8018 : MOV #5h,W0 <-- (2) 801a : MOV W0,[W15++] <-- (2) 801c : MOV #2h,W0 <-- (1) 801e : MOV W0,[W15++] <-- (1) 8020 : MOV #3h,W0 <-- (1) 8022 : MOV W0,[W15++] <-- (1) 8024 : MOV #4h,W0 <-- (1) 8026 : MOV [--W15],W2 <-- (1) 8028 : MUL.SS W2,W0,W0 <- (1) 802a : ADD W0,[--W15],W0 (1) 802c : MOV [W14+4h],W2 802e : MOV [--W15],W1 <-- (2) 8030 : ADD W1,W1,W1 <-- (2) 8032 : ADD W1,W2,W1 <-- (2) 8034 : MOV W0,[W1] <-- (2) 8036 : MOV [W14+4h],W0 8038 : MOV W0,[W15++] <-- (2') 803a : MOV #5h,W0 <-- (2') 803c : MOV [--W15],W1 <-- (2') 803e : ADD W0,W0,W0 <-- (2') 8040 : ADD W0,W1,W0 <-- (2') 8042 : MOV [W0],W0 <-- (2') 8044 : MOV W0,[W14+6h] 8046 : MOV [W14+6h],W0 <- (3) 8048 : MOV W0,[W14+2h] 804a : MOV [W14+2h],W0 <- (3') 804c : ULNK 804e : RETURN 8050 : LNK #0 8052 : MOV #1887h,W0 8054 : RCALL 163eh 8056 : MOV [bceh],W0 8058 : RCALL 800ch 805a : RCALL 17eah 805c : ULNK 805e : RETURN abc = 14 : |
:l 1:# optimized code test 2: 3:func abc( x ) { 4: var ar, y; 5: 6: ar = x; 7: ar[ 5 ] = 2+3*4; 8: y = ar[ 5 ]; 9: return = y; 10:} 11: 12: 13:proc main() { 14: PrnStr_( "¥n abc = " ); 15: PrnDec_( abc( Array_ ) ); 16:} :run 8000 : MOV W15,[e70h] 8002 : MOV W14,[e72h] 8004 : BRA 802ah 8006 : MOV [e72h],W14 8008 : MOV [e70h],W15 800a : RETURN 800c : LNK #8 800e : MOV W0,[W14+0h] 8010 : CLR W0 8012 : MOV W0,[W14+2h] 8014 : MOV [W14+0h],W0 8016 : MOV W0,[W14+4h] 8018 : MOV #eh,W0 <-- (1) 801a : MOV [W14+4h],W2 801c : MOV W0,[W2+ah] <-- (2) 801e : MOV [W14+4h],W1 8020 : MOV [W1+ah],W0 <-- (2') 8022 : MOV W0,[W14+6h] 8024 : MOV [W14+6h],W0 <-- (3) 8024 : MOV W0,[W14+2h] 8026 : MOV [W14+2h],W0 <-- (3') 8026 : ULNK 8028 : RETURN 802a : LNK #0 802c : MOV #1887h,W0 802e : RCALL 2a72h 8030 : MOV [be4h],W0 8032 : RCALL 800ch 8034 : RCALL 2c1eh 8036 : ULNK 8038 : RETURN abc = 14 : |
[TOP] [ 前へ ] 連載記事 [ 次へ ]
コメント 0