2011年6月29日水曜日

Conditional execution 再び

ノッポさんに「やるんだよ」と言われてはや半年.
ふと思い立って,frv なる CPU の conditional execution をまねて *.md 書いてみた.
まずは,条件実行つき mov 命令.
(define_insn "*cond_exec_mov"
  [(cond_exec
    (match_operator 0 "comparison_operator"
			[(match_operand 1 "int_mode_flags" "")
			 (const_int 0)])        ←ここら辺までが条件実行
    (set (match_operand:INT 2 "register_operand" "=r") ←ここら辺が mov 命令
	 (match_operand:INT 3 "liw_signed"       "")))]
  "TARGET_COND_EXEC"
  "mov_%b0 %3,%2"
  [(set_attr "timings" "11")]
)

でコンパイル結果は,
int hoge( int a, int b, int c, int d ){
    if( a > b ) a = c;
    else        a = d;
    return a;
}
  ↓↓↓↓↓↓
_hoge:
	cmp d1,d0
	mov_gt a0,d0
	mov_le a1,d0
	retf [],0
うっしゃあ.意外とあっさりと成功 ヘ(^∇^ヘ)ヘ(^∇^ヘ) ウヒョヒョ

よーし,パパ全命令に条件実行つけちゃうぞー.
てな訳でまずは add に足してみた.
(define_insn "*cond_exec_addsi"
  [(cond_exec
    (match_operator 0 "comparison_operator"
			[(match_operand 1 "int_mode_flags" "")
			 (const_int 0)])
      (set (match_operand:SI          2 "register_operand"  "=r") ←add命令
	   (plus:SI (match_operand:SI 3 "register_operand"  "%r")
		    (match_operand:SI 4 "nonmemory_operand" "")))
  )]
  "TARGET_COND_EXEC"
  "add_%b0 %4,%3,%2"
  [(set_attr "timings" "11")]
)

そのコンパイル結果は,
int hoge( int a, int b, int c, int d ){
    if( a > b ) a = b + c;
    else        a = c + d;
    return a;
}
  ↓↓↓↓↓↓
_hoge:
	cmp d1,d0
	bgt .L5
	add a1,a0,d0
	retf [],0
.L5:
	add a0,d1,d0
	retf [],0

ぐはぁっ
全然効いてないよ~(゜ーÅ)ほろり

理由がよくわからなかったので,gcc に -fdump-rtl-all オプションをつけて,最適化過程の全 RTL をダンプさせてみた.
if-then-else のブランチ命令から conditional-execution への変換は,ce3 なるステージで行われているらしいので,その直前の peephole2 ステージの RTL の,当該 add 命令の RTL を見てみる.
(insn 11 10 41 3 (parallel [
            (set (reg/v:SI 0 d0 [orig:58 a ] [58])
                (plus:SI (reg/v:SI 1 d1 [orig:61 b ] [61])
                    (reg/v:SI 4 a0 [orig:62 c ] [62])))
            (clobber (reg:CC 51 EPSW))
        ]) z.c:11 11 {addsi3}
大雑把に言って,(define_insn "*cond_exec_addsi"... のところに書いた (set ...) のパターンがここの (set ...) のパターンにマッチすれば,条件実行つき add に変換されるはずなんだけど,(clobber (reg:CC 51 EPSW)) ってのがあるせいでマッチできない.
(clobber (reg:CC 51 EPSW)) ってのは「add 命令実行したらフラグレジスタが更新されるよ」って意味なのであって当たり前なのだが,一方条件実行つき add にはフラグ更新機能はつけてはいけない.
しかし,パターンをマッチさせるには,通常 add 命令のフラグ更新をやめるか,条件付実行の add にフラグ更新をさせるか,のどちらかしかない (実際にはどっちも実 CPU の動作からウソを付くことになるので,おかしなコードを吐く可能性がある)

ARM とかどうやってんのかと思って見たら,元々通常 add 命令でフラグ更新する・しないが選択できるので,何の問題もないのね.

んー,困った.

0 件のコメント:

コメントを投稿