SSブログ
English Version

独自言語 picle のコンパイラ化(その6) [PIC]

 picleコンパイラ製作の続編です。

 前回公開したVer0.01では main() 内で「}」 が不足した場合、ソース領域を超えて解析してしまう問題があったのでパース途中でソースエンドになった場合、エラー検出するようにしました ^^;
  1. コンパイルの最適化
     次の最適化を盛り込みました。
     対応前後のコンパイル結果比較を末尾に示します。

    • (1) 直値の事前計算
       数式内で直値同士の計算はコンパイル時に行うようにした。
       直値計算でゼロ除算が発生した場合、コンパイル時に実行時のゼロ除算と同様なメッセージが表示される。
      :{var a;a=2/(6-2*3);}
      Divided by 0 err :/(6-2*3);}
      :
    • (2) 配列アクセスの最適化
       インデックスが 10 bit 以内の場合、PIC24 には直値インデックス付きインダイレクトアドレッシングのMOV命令があるので利用するようにした。

    • (3) 連続したセーブ&ロードの最適化
       ローカル変数値を設定直後に参照する場合、参照コードを削除した。
       但し、単純に削除すると他からのジャンプ先になっている場合、値が設定されないのでジャンプ先の場合は削除対象外とした。
       下記の最適化後(右側)で次の行のアドレスが進んでいない行が削除された命令。


  2. 制御構文の追加
     下記の最適化の前後比較は動作確認のため意図的に最適化にヒットするように作った処理自体は意味の無いソースなので通常のソースでは効果はそれ程無いものと思っています。
     反面コンパイラのサイズが増大しコンパクト性という利点を失いつつ(かつ内部ロジックが複雑化)の変更なので改悪になるかもしれません。
     ということでもっと効果的な変更をした方がいいと思い直し、制御文を2つ追加しました(こちらはソース的にもわずかな追加)

    • else if 文の実装
       else if が無いとソースのインデントが深くなってしまうので (使い易さ/ソース増) で言えばこちらの方が改善と思う。
       「else if」は1つのワード扱いなので perl の elsif 等のように一語にすべきかとも思ったが見慣れたスタイル(人にもよるけど)ということでC言語スタイルにした。
       パースを簡略化しているので 「else」と「if」の間がスペース2個以上だったりするとエラーになる w

    • while { } 文の実装
       for 文で代用できるのでなくても良いかなぁと思っていたがやはりあった方がソースが見やすくなるので追加した。

  3. ダウンロード
     今回の変更版は下記リンクの記事からダウンロードできます。
       独自言語 picle compiler on PIC24FJ

最適化の効果(公開版ではアセンブルリストは表示されません)
beforeafter
: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] [ 前へ ] 連載記事 [ 次へ ]
nice!(0)  コメント(0)  トラックバック(2) 
共通テーマ:趣味・カルチャー

nice! 0

コメント 0

コメントを書く

お名前:
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

トラックバック 2