レジスタ割り当ての最適化

rowl1で

plus: (x,y) {
    return x+y;
};

コンパイルすると、中間コードが

_plus.ii2TiL:
        pushl %ebp
        movl %esp, %ebp
        movl 12(%ebp), %p9
        movl 8(%ebp), %p8
        movl %p8, %p10
        addl %p9, %p10
        movl %p10, %eax
        leave
        ret

になる。%p8,%p9,%p10がレジスタ未割り当ての変数。今朝のレジスタ割り当ての実装だと、これが

_plus.ii2TiL:
        pushl %ebp
        movl %esp, %ebp
        movl 12(%ebp), %eax
        movl 8(%ebp), %ebx
        movl %eax, %ecx
        addl %ebx, %ecx
        movl %ecx, %eax
        leave
        ret

になってた。流石にこれはカッコ悪いので最適化した。
方法は

        movl X, Y

という行がある場合、XとYに同じレジスタ・スタック領域を割り当てられるとこのコピーが消せるという典型的な物。
実際は割り当ての順番とかいろいろコスト計算している。出力レジスタはスタックよりレジスタの方が良さそうだとか、そういうヒューリスティクスをなんとなく使っている。

結果

_plus.ii2TiL:
        pushl %ebp
        movl %esp, %ebp
        movl 8(%ebp), %eax
        addl 12(%ebp), %eax
        leave
        ret

とても賢くなった。本当はスケジューリングもすべきだけど、これで良しとしときます。