最適化の範囲: p0 ~ p1
for (p = p0; p < p1; p = 次の命令) {
if (pの命令がCmpEq~CmpRnz) { r = p; (この命令の場所を覚えておく) }
if (pの命令がSetCc && 次の命令がCmpEqかCmpNeで定数0との比較 && SetCcの結果をその先で一切使わない) {
if (次の命令がCmpEq) { rに書いてある命令の比較条件を反転させる }
pのSetCc命令をNopにしてしまう
pの次のCmpEq/CmpNe命令もNopにしてしまう
}
}if ((a > 1) != 0) goto label; // HLX-001が内部的に生成する共通中間コードをC言語風に書いたもの 1: CmpGt(a, 1); // (最適前)上記を共通中間コードで表したもの 2: SetCc(tmp); // この2行目と3行目は最適化によって消される 3: CmpNe(tmp, 0); 4: Jcc(label); 1: CmpGt(a, 1); // (最適化後)このようにうまくいく 2: Jcc(label);
最適化の範囲: p0 ~ p1
変数の値を記憶するテーブルを初期化
for (p = p0; p < p1; p = 次の命令) {
定数代入命令があったら、テーブルに変数の値を登録
その他、結果が定数になるような演算があれば、それも結果をテーブルに登録
もし定数のみの演算ではなく結果が定数じゃないかもしれないと思われるときは、テーブルから変数に関する行を削除
命令の中で変数が使われていたら、その変数がテーブルに登録されていないかを確認し、登録されていれば定数値に置換する
ラベル宣言文に当たったら、テーブルをいったん全クリアする(もうどの変数に定数値がはいっているか分からないので)
}最適化の範囲: p0 ~ p1
for (p = p0; p < p1; p = 次の命令) {
if (pの命令がJmpかJcc) {
分岐先の命令を見る(NOPなどは読み飛ばす)
もしJmpだったら、分岐先を修正
}
}最適化範囲: p0 ~ p1 関数の先頭から見て行って、Jcc/Jmpを見つけたら、スタックにそのラベルを登録。RetやJmpを見つけたら、そこで終わり。 終わったら、スタックを見に行って、もしラベルが登録されていればそこからまた見て行ってJcc/Jmpが来たらスタックに登録。・・・これを繰り返す。 同じラベルを二度見に行かないようにフラグで管理。 こうすることで、どうやっても到達しないラベルにはフラグが付いていないことになるので、フラグのないラベルは消す。 その上で、Jmpの後でラベル宣言命令までの間は、どうやっても到達しないコードになるので、これを削る。
最適化範囲: p0 ~ p1
for (p = p0; p < p1; p = 次の命令) {
if (pの命令がJmpかJcc) {
if (pの次の命令がラベル宣言 && そのラベルはpの分岐先と同じ) {
pの分岐命令を消す
}
}
}最適化範囲: p0 ~ p1
for (p = p0; p < p1; p = 次の命令) {
命令の開始位置を配列t[i]に記憶させる(以下で、命令を逆順にたどりたいので)
}
for (i--; i >= 0; i--) {
p = t[i];
if (pの演算結果が次のCpyでしか使われていない) {
Cpyの代入先へ直接代入するようにする
そしてCpyは消す
[註] ここは以下のようなコードを最適化する
tmp = a + b; c = tmp; → c = a + b;
}
if (pの演算結果がその先で使われていない) {
pの命令を消す
}
}unroll(11)
for (s = i = 0; i <= 10; i++) {
s = s + i;
}
print s;
// アンロール結果:
s = i = 0; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
s = s + i; i++; if (i > 10) goto brk;
lop:
s = s + 1; i++;
if (i <= 10) goto lop;
brk:
print s;
このあと、最適化によって、定数畳み込みや定数伝播がおきて、if文が消えたりただのgotoになったりして、使わないラベルや直後への分岐も消えて、
print 55;
だけになります。| コメント | お名前 | NameLink | |