レジスタ割り当ての最適化
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
とても賢くなった。本当はスケジューリングもすべきだけど、これで良しとしときます。