secondboot.cs/最適化


secondboot.cs

最適化の実際

CILはレジスタのないスタックマシンを想定しています。次のようなC#のソースから

int a = 1, b = 2, c = a + b;

次のようなCILが生成されます。

ldc.i4.1
stloc.0
ldc.i4.2
stloc.1
ldloc.0
ldloc.1
add
stloc.2

乱暴に言うとldがpushでstがpopです。i4はint型のことで、ldc.i4というのは後続の即値をスタックに積んでいます。locというのはローカル変数が置かれるスタックで、この場合はaが0、bが1、cが2に割り当てられています。つまり変数への代入は一度スタックに積んでそれを取ることで表現されています。

これを単純に8086の16bitコードに変換すると次のようになります。(bpはローカル変数のスタックの先頭を指しているとします)

; ldc.i4.1
mov	ax,	1
push	ax
; stloc.0
pop	word [ss:bp-2]
; ldc.i4.2
mov	ax,	2
push	ax
; stloc.1
pop	word [ss:bp-4]
; ldloc.0
push	word [ss:bp-2]
; ldloc.1
push	word [ss:bp-4]
; add
pop	dx
pop	ax
add	ax,	dx
push	ax
; stloc.2
pop	word [ss:bp-6]
(33バイト)

一見して分かるようにスタックを経由して代入を表現しているため冗長です。popに対応するpushを見つけて直接代入のmovに置き換えることで8086らしくなります。

mov	ax,	1
mov	word [ss:bp-2],	ax
mov	ax,	2
mov	word [ss:bp-4],	ax
mov	ax,	word [ss:bp-2]
mov	dx,	word [ss:bp-4]
add	ax,	dx
mov	word [ss:bp-6],	ax
(28バイト)

代入にいったんaxを経由して冗長な部分は、三段論法(a=bかつb=cならa=c)で即値代入に最適化します。

mov	word [ss:bp-2],	1
mov	word [ss:bp-4],	2
mov	ax,	word [ss:bp-2]
add	ax,	word [ss:bp-4]
mov	word [ss:bp-6],	ax
(24バイト)

ローカル変数をレジスタに割り当てればかなりすっきりします。

mov	ax,	1
mov	bx,	2
mov	cx,	ax
add	cx,	bx
(10バイト)

というかこれは人間が手で書けば当たり前の書き方でしかないですね。実はここで言っている最適化の実態は、そういうコードがうまく出るように調整しているに過ぎません。

これは最適化の初歩の初歩で、高度なコンパイラではフローを書き換えたりと複雑な最適化を行います。今回はそこまではやりませんので悪しからず。

出力サイズ

コメント

コメントはありません。 コメント/secondboot.cs/最適化?

お名前:

MENU

now: 4

リンク


最新の20件
2018-10-07 2018-09-20 2018-09-03 2018-05-09 2017-09-29 2017-01-10 2016-12-11 2016-10-04 2016-08-14 2016-05-29 2015-12-28 2013-02-25 2013-02-21 2013-02-20 2013-02-12 2013-02-11 2013-02-10
最新の20件
2010-02-01 2010-01-31 2010-01-30 2010-01-29 2010-01-16

Counter: 2766, today: 1, yesterday: 0

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS

Last-modified: 2008-03-28 (金) 15:48:01 (3915d);  Modified by mona
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji
Powered by PHP 5.2.17
HTML convert time to 0.037 sec.